CF1776J Italian Data Centers 题解
Kelvin2009 · · 题解
只是一道几何分析加全源最短路。
首先,考虑对单个点的分裂状态。
将一个点分裂后的第一个点记为该点的 0 号,第二个点为 1 号。
则
可以发现,两个点的状态标号在只有其中某一位上不同时,才会连边。这实际上是一个
建议参考这篇
一个超立方体上可以被经过的最长的最短路长为
其次,考虑两个超立方体之间的连边。
由于是最短路,在单个超立方体上的移动至多进行一次,最大为
对于连边:颜色相同的超立方体在每次二进制位延展(从第
一个点简化为了两个状态,可以用 floyed 求出各个点两两之间的最短路。
寻找最长的最短路,可以先找最长的最短环,再破为两半。固定一个顶点
代码:
#include<bits/stdc++.h>
using namespace std;
const int range=605;
const int lim=0x3f3f3f3f;
int n,m,k;
int c[range];
int grab[range][range],ans;
inline int get(int u,bool op)
{
return op*n+u;
}
int main()
{
memset(grab,lim,sizeof(grab));
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=n;i++)
{
scanf("%d",&c[i]);
grab[i][i]=grab[get(i,1)][get(i,1)]=0;
grab[get(i,1)][i]=grab[i][get(i,1)]=k;
}
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
if(c[u]==c[v])
{
grab[get(u,0)][get(v,0)]=grab[get(v,0)][get(u,0)]=1;
grab[get(u,1)][get(v,1)]=grab[get(v,1)][get(u,1)]=1;
}
else
{
grab[get(u,0)][get(v,1)]=grab[get(v,0)][get(u,1)]=1;
grab[get(u,1)][get(v,0)]=grab[get(v,1)][get(u,0)]=1;
}
}
int ran=2*n;
for(int kk=1;kk<=ran;kk++)
{
for(int i=1;i<=ran;i++)
{
for(int j=i+1;j<=ran;j++)
{
grab[j][i]=grab[i][j]=min(grab[i][j],grab[i][kk]+grab[kk][j]);
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
ans=max(ans,(grab[i][get(j,0)]+grab[i][get(j,1)]+k)/2);
}
}
printf("%d",ans);
return 0;
}