正题
评测记录:https://www.luogu.org/recordnew/lists?uid=52918&pid=P1522
题目大意
有n个点,连接任意两个不同联通块上的点,使这个新的联通块之间最远的两个点的距离最远。
解题思路
先FlodyO(n3)O(n^3)O(n3)计算两两之间的距离
然后计算出每个点最远的点的距离,之后对于枚举两个不同联通块中的点,那么可能产生的新的权值就是两个个点的最远的点距离加上这两个点之间的距离,但是还要和合并前联通块中最远的点的距离比较
code
// luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<iostream>
#define N 160
#define pows(x) x*x
using namespace std;
int n,inx[N],tot;
double x[N],y[N],a[N][N],d[N],md[N],mins;
char c;
double const_dis(int i,int j)
{return sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
}
void dfs(int x)//分联通块
{inx[x]=tot;for(int i=1;i<=n;i++)if(!inx[i]&&a[x][i]!=2147483647)dfs(i);
}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%lf%lf",&x[i],&y[i]);for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){cin>>c;if(c=='1')a[i][j]=const_dis(i,j);else if(i!=j) a[i][j]=2147483647;}for(int i=1;i<=n;i++)if(!inx[i]) tot++,dfs(i);for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++)if(a[i][k]+a[k][j]<a[i][j])a[i][j]=a[i][k]+a[k][j];//计算最短路for(int i=1;i<=n;i++){for(int j=1;j<=n;j++)if(a[i][j]!=2147483647)md[i]=max(md[i],a[i][j]);//每个点的最远距离d[inx[i]]=max(d[inx[i]],md[i]);//每个联通块最远距离}mins=2147483647;for(int i=1;i<n;i++)for(int j=i+1;j<=n;j++)if(inx[i]!=inx[j])mins=min(mins,max(md[i]+md[j]+const_dis(i,j),max(d[inx[i]],d[inx[j]])));printf("%.6lf",mins);
}