牛的旅行 Cow Tours,洛谷之提高历练地,最短路问题

正文

      第六题:牛的旅行 Cow Tours

      这题看上去好像很烦,其实题意就是说有很多个点,被分成若干个联通块,图中有边,定义一个图的直径是最远两个点的路径长度。所以很明显了,我们只要算出一个点到当前联通块其他点的最长路径。就可以暴力枚举不同联通块的每个点,算出距离加上前面预处理好的那个到当前联通块的最长路,更新min即可。

      最后还要判断原来集合的直径是否比现在的集合还大,那么就直接输出原来集合。

代码<恶心>

#include
#include
#include
#include
#include
using namespace std;

double max_d[160];
int n;
struct node{
	double x,y;
}s[160];
double dis[160][160];
double ans=0;

double distan(int x,int y){
	double x1=s[x].x,x2=s[y].x,y1=s[x].y,y2=s[y].y;
	return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%lf %lf",&s[i].x,&s[i].y);
	for(int i=1;i<=n;i++){
		char c[160];
		scanf("%s",c+1);
		for(int j=1;j<=n;j++){//处理在同一集合的路径长度
			int x=c[j]-'0';
			if(x) dis[i][j]=distan(i,j);
			else if(i!=j) dis[i][j]=1061109567;
		}
	}
	for(int k=1;k<=n;k++)
		for(int i=1;i<=n;i++)
			for(int j=1;j<=n;j++)//处理距离
				if(dis[i][j]>dis[i][k]+dis[k][j])
					dis[i][j]=dis[i][k]+dis[k][j];
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++){//处理点到当前联通块的距离最大值
			if(dis[i][j]!=1061109567) max_d[i]=max(max_d[i],dis[i][j]);
			if(max_d[i]>ans) ans=max_d[i];
		}
	double min_d=1e9;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++){//暴力枚举不同联通块的两个点
			if(i==j || dis[i][j]!=1061109567) continue;
			double p=distan(i,j);
			if(max_d[i]+max_d[j]+p

你可能感兴趣的:(牛的旅行 Cow Tours,洛谷之提高历练地,最短路问题)