洛谷1522 牛的旅行 floyed

 点少,标准的floyed。先用floyed更新出任意两点之间的最短距离。用并查集标记在同一牧场的的点。最后枚举两个不同牧场的点之间的距离len3,以及各自和自己牧场中最远的距离len1,len2.我们求的结果就是最小的(len1+len2+len3)。

然后第七个点一直过不去。后来发现,少考虑了一种情况,就是可能两个原牧场中的某一个直径可能大于len1+len2+len3。。。。。。。。。。找了三个小时

#include <bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define res register int 
const int maxn=155;
char G[maxn][maxn];
double dis[maxn][maxn];
int fa[maxn];
int N;
struct Node{
	double x,y;
}node[maxn];
double cal(int a,int b){
	return sqrt(abs(node[a].x-node[b].x)*abs(node[a].x-node[b].x)+abs(node[a].y-node[b].y)*abs(node[a].y-node[b].y));
}
int find(int x){
	if(x==fa[x]) return x;
	else return fa[x]=find(fa[x]);
}
void unit(int x,int y){
	x=find(x);
	y=find(y);
	if(x!=y) fa[x]=y;
	return;
}
void init()
{
	cin>>N;
	for(res i=1;i<=N;i++){
		fa[i]=i;
		scanf("%lf%lf",&node[i].x,&node[i].y);
	}
	for(res i=1;i<=N;i++){
		char temp[maxn];
		scanf("%s",temp);
		sprintf(G[i],"#%s",temp);
	}
	for(res i=1;i<=N;i++)
		for(res j=1;j<=N;j++)
			dis[i][j]=inf;
	for(res i=1;i<=N;i++){
		for(res j=1;j<i;j++){
			if('1'==G[i][j]){
				unit(j,i);
				dis[i][j]=dis[j][i]=cal(i,j);
			}
		} 
	}
	for(res i=1;i<=N;i++)
		dis[i][i]=0;
}

void floyed()
{
	for(res k=1;k<=N;k++)
		for(res i=1;i<=N;i++)
			for(res j=1;j<=N;j++)
				dis[i][j]=dis[j][i]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
int main()
{
	init();
	floyed();
	double len=inf;
	for(res i=1;i<=N;i++)
		for(res j=i+1;j<=N;j++){
			double len1=-inf,len2=-inf,len3=-inf;//len1表示的是第一个牧场到该点的距离 len2是第二个  len3表示的是两点之间的距离 
			if(find(i)!=find(j)){
				len3=cal(i,j);
				//开始找第i个点所在牧场里面所有的点到i点最大的距离 
				for(res k=1;k<=N;k++)
					if(find(k)==find(i)) len1=max(len1,dis[i][k]);
				//开始找第j个点所在牧场里面所有的点到j点最大的距离 
				for(res k=1;k<=N;k++)
					if(find(k)==find(j)) len2=max(len2,dis[j][k]);
				len=min(len,len1+len2+len3);
			}	
		}
	printf("%.6lf",len);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41755258/article/details/84927616