题目:https://www.luogu.org/problemnew/show/P1522
或者http://111.231.101.32/problem.php?id=1001(自建OJ,欢迎光临)
分析:
step1、用floyed求出任两点最短路径;
step2、求出同一联通块中任一点可以到达的最远距离,记作maxdis[i],并求出maxdis[i]的最大值maxx1;
step3、枚举不联通的两个点,求出maxdis[i]+maxdis[j]+(i,j间的距离)中的最小值maxx2;
step4、输出答案max(maxx1,maxx2)。
为什么输出max(maxx1,maxx2),下图可以非常直观地说明,答案显而易见是20.000000:
AC代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
int a[155][2];
double dis[155][155],maxdis[155];
double dist(int i,int j){
return sqrt( (double)( (a[i][0]-a[j][0])*(a[i][0]-a[j][0]) )
+ (double)( (a[i][1]-a[j][1])*(a[i][1]-a[j][1])) );
}
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i][0]>>a[i][1];
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j)dis[i][j]=1e15;
char x;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
cin>>x;
if(x=='1'){
dis[i][j]=dist(i,j);
}
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=k && j!=k && i!=j
&& dis[i][j]>dis[i][k]+dis[k][j])
dis[i][j]=dis[i][k]+dis[k][j];
double maxx1=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(i==j)continue;
if(dis[i][j]<1e15
&& maxdis[i]<dis[i][j])
maxdis[i]=dis[i][j];
}
if(maxx1<maxdis[i])maxx1=maxdis[i];
}
double maxx2=1e15;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
if(i==j)continue;
if(dis[i][j]==1e15
&&maxx2>maxdis[i]+maxdis[j]+dist(i,j) )
maxx2=maxdis[i]+maxdis[j]+dist(i,j);
}
printf("%.6f\n",maxx1>maxx2?maxx1:maxx2);
return 0;
}