【解题思路】
- 用Floyed求出任两点间的最短路,然后求出每个点到所有可达的点的最大距离,记做m[i]。(Floyed算法)
- r1=max(m[i])
- 然后枚举不连通的两点i,j,把他们连通,则新的直径是m[i]+m[j]+(i,j)间的距离。
- r2=min(m[i]+m[j]+dis[i,j])
- re=max(r1,r2) re就是所求。
【参考代码】
#include <bits/stdc++.h>
using namespace std;
int zb[155][2];
double dist[155][155],m[155];
int n;
double dis(int x,int y){
return sqrt((zb[x][0]-zb[y][0])*(zb[x][0]-zb[y][0])+(zb[x][1]-zb[y][1])*(zb[x][1]-zb[y][1]));
}
void Floyd(){//搜索路径
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if((i!=j)&&(i!=k)&&(j!=k)&&(dist[i][k]<1e10)&&(dist[k][j]<1e10)&&(dist[i][j]>dist[i][k]+dist[k][j]))
dist[i][j]=dist[i][k]+dist[k][j];
}
int main() {
cin>>n;
for(int i=1;i<=n;i++)cin>>zb[i][0]>>zb[i][1];
char c;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
cin>>c;
if(c=='1')
dist[i][j]=dis(i,j);
else dist[i][j]=1e10;
}
Floyd();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(dist[i][j]<1e10&&m[i]<dist[i][j]) m[i]=dist[i][j];
double minx=1e20,t;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j && dist[i][j]==1e10){
t=dis(i,j);
if(minx>m[i]+m[j]+t)minx=m[i]+m[j]+t;
}
for(int i=1;i<=n;i++) minx=max(minx,m[i]);
printf("%.6lf",minx);
return 0;
}