题意
给几个联通图(>=2个),每个联通图的直径为图中任意两点最短距离的最大值,然后将任意2点(在不同的联通图中)用一个路径连起来(路径是有长度的),问连通后最小的这个直径是多少。刚开始是先用并查集合并一波,然后每个dfs一遍,找到离其最远的点(同一个联通图中)存如len中(len就是这个点与这个图的结点的最远距离),然后将距离连起来,枚举这个路径连接全部的点,找到连接后的最小值,这个值为这两个点的len+两个点的距离,然后其实是错误的,因为有可能这两个点的len+这两个点的距离还没有其图本身另外2个点的最远距离还远。搞了一整个上午+半个下午才搞定。
1、wa了好多发,刚开始是tle,本来以为数据范围小直接跑单源最短路即可,但是超时用了vector来优化。
2、wa是因为题意点没考虑全。!
/*
ID: 13227851
PROG: cowtour
LANG: C++
*/
#include <iostream>
#include <iomanip>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <map>
#include <vector>
#include <algorithm>
#include <set>
#include <queue>
#include <math.h>
using namespace std;
struct ttt{
long double x,y;
};
ttt q1[180];
vector<int>gg[180];
long double map1[180][180];
int pre[180];
void init(){
for(int i=1;i<=160;i++)
pre[i]=i;
}
int find1(int x){
int r=x;
while(r!=pre[r]){
r=pre[r];
}
int i=x,j;
while(pre[i]!=r){
j=pre[i];
pre[i]=r;
i=j;
}
return r;
}
int find2(int x,int y){
int x1=find1(x);
int y1=find1(y);
if(x1!=y1){
pre[y1]=pre[x1];
}
}
long double ggg[200];
long double dist[180];
long double len[180];
int fun(int x){
int i,j;
for(i=1;i<=160;i++)
dist[i]=1e9+7;
dist[x]=0;
queue<int>qq;
qq.push(x);
long double max1=0;
while(!qq.empty()){
int u=qq.front();qq.pop();
for(j=0;j<gg[u].size();j++){
i=gg[u][j];
if(map1[u][i]!=-1&&map1[u][i]+dist[u]<dist[i]){
dist[i]=dist[u]+map1[u][i];
qq.push(i);
}
}
}
for(i=1;i<=160;i++)
if(dist[i]!=1e9+7)
max1=max(max1,dist[i]);
len[x]=max1;
ggg[find1(x)]=max(ggg[find1(x)],max1);
}
char s1[2000];
long double map2[180][180];
long double dist2[200];
int main(){
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
freopen("cowtour.in","r",stdin);
freopen("cowtour.out","w",stdout);
int i,j,f1,f2,f3,l1,t1,t2,t3,t4,l2,l3;
int m,r;
int T,n;
memset(ggg,0,sizeof(ggg));
memset(q1,0,sizeof(q1));
memset(map1,-1,sizeof(map1));
memset(map2,0,sizeof(map2));
memset(len,0,sizeof(len));
cin >> n;
long double g1,g2,g3,g4;
init();
for(i=1;i<=n;i++){
cin >> q1[i].x >> q1[i].y;
}
char a,b;
for(i=1;i<=n;i++){
cin >> s1;
for(j=0;j<n;j++){
a=s1[j];
if(i==j+1)continue;
if(a=='1'){
gg[i].push_back(j+1);
gg[j+1].push_back(i);
map1[i][j+1]=sqrt((q1[i].x-q1[j+1].x)*(q1[i].x-q1[j+1].x)+
(q1[i].y-q1[j+1].y)*(q1[i].y-q1[j+1].y));
map2[i][j+1]=map1[i][j+1];
map2[j+1][i]=map1[i][j+1];
map1[1+j][i]=map1[i][j+1];
find2(i,j+1);
//cout <<i << " " << j+1 << "!~~! " << map2[i][j+1] << endl;
}
}
}
for(i=1;i<=n;i++)
dist2[i]=0;
//cout << map2[2][1] << endl;
for(int k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
if(i==1&&j==2&&k==3){
// cout <<map2[1][3]<<"!!" << map2[1][2] << " ~~~~ " << map2[2][3] << endl;
}
if(map2[i][j]!=0&&map2[j][k]!=0)
if(map2[i][k]==0||map2[i][j]+map2[j][k]<map2[i][k]){
map2[i][k]=map2[i][j]+map2[j][k];
map2[k][i]=map2[i][k];
// cout << i << " ~~~ " << k << " " << map2[i][k] << endl;
}
}
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
if(map2[i][j]!=0&&i!=j){
dist2[i]=max(dist2[i],map2[i][j]);
// cout << i << " 到" << j << "的距离为" << map2[i][j] <<endl;
}
}
}
//cout << map2[1][3] << "!!!!! "<< endl;
for(i=1;i<=n;i++){
fun(i);
// cout << i << "的最大 " <<len[i] << " " << dist2[i] << endl;
}
long double min1=1e9+7;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
if(i!=j&&find1(i)!=find1(j)){
long double len1=sqrt((q1[i].x-q1[j].x)*(q1[i].x-q1[j].x)+
(q1[i].y-q1[j].y)*(q1[i].y-q1[j].y));
//if(min1>len1+dist2[i]+dist2[j]){
//cout << "连接" << i << "到" << j << endl;
long double len2=max(len1+len[i]+len[j],ggg[find1(i)]);
len2=max(ggg[find1(j)],len2);
min1=min(min1,len2);
//}
}
}
cout << setiosflags(ios::fixed) << setprecision(6) <<min1<< endl;
//printf("%.6LLf\n",min1);
return 0;
}