用floyd计算每个点可达的最短距离,然后统计每个点可达距离的最大长度。然后用并查集计算每个点所属的集合,枚举两个不同集合a、b里的两个点i、j,从所有的max
{edge[a],edge[b],distance(i,j)+l(i)+l(j)},其中edge[x]表示集合x的直径,distance(x,y)表示x和y点的距离,l(x)表示点x可达距离的最大长度。
#include <iostream>
#include <cstdio>
#include <map>
#include <vector>
#include <string>
#include <stack>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
/*
ID: kkkwjx1
PROG: cowtour
LANG: C++
*/
typedef long long LL;
const int maxn=155;
const double inf=1e15;
double g[maxn][maxn];
int x[maxn],y[maxn];
double edge[maxn];
double dist(double x1,double y1,double x2,double y2)
{
return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int father[maxn];
int find(int p)
{
return p==father[p]?p:father[p]=find(father[p]);
}
void merge(int a,int b)
{
int fa=find(a),fb=find(b);
if(fa!=fb)
father[fa]=fb;
}
int main()
{
freopen("cowtour.in","r",stdin);
freopen("cowtour.out","w",stdout);
int n;
scanf("%d",&n);
for(int i=1; i<=n; ++i)
scanf("%d%d",&x[i],&y[i]);
for(int i=0; i<=n; ++i)
for(int j=0; j<=n; ++j)
if(i==j)
g[i][j]=0;
else
g[i][j]=inf;
for(int i=1; i<=n; ++i)
father[i]=i;
for(int i=1; i<=n; ++i)
{
char str[maxn];
scanf("%s",str);
for(int j=1; j<=n; ++j)
{
if(str[j-1]=='1')
{
merge(i,j);
g[i][j]=g[j][i]=dist(x[i],y[i],x[j],y[j]);
}
}
}
for(int k=1; k<=n; ++k)
{
for(int i=1; i<=n; ++i)
{
for(int j=1; j<=n; ++j)
if(g[i][k]!=inf&&g[k][j]!=inf)
g[i][j]=min(g[i][j],g[i][k]+g[k][j]);
}
}
for(int i=1; i<=n; ++i)
for(int j=1; j<=n; ++j)
if(g[i][j]!=inf)
g[i][i]=max(g[i][i],g[i][j]);
for(int i=1; i<=n; ++i)
{
int fa=find(i);
edge[fa]=max(edge[fa],g[i][i]);
}
double ans=inf;
for(int i=1; i<=n; ++i)
{
for(int j=i+1; j<=n; ++j)
{
int fa=find(i),fb=find(j);
if(fa!=fb)
{
double dis=dist(x[i],y[i],x[j],y[j])+g[i][i]+g[j][j];
dis=max(dis,max(edge[fa],edge[fb]));
ans=min(ans,min(dis,res));
}
}
}
printf("%.6f\n",ans);
return 0;
}