USACO Cow Tour

来源:互联网 发布:广电网络机顶盒 编辑:程序博客网 时间:2024/06/05 02:38

  挺麻烦的一道题,细心一点,主要一会最大一会最小的容易把自己搞混乱。

/*ID: jinusac1PROG: cowtourLANG: C++*/#include <iostream>#include <cstdio>#include <cmath>using namespace std;double pos[160][2];double dis[160][160]={0};double Pt[160][160]={0};double ffar[160]={0};double diameter[160]={0};int set[160];int getfather(int x){if(set[x]==x) return x;set[x]=getfather(set[x]);return set[x];}int main(){freopen("cowtour.in","r",stdin);freopen("cowtour.out","w",stdout);int n;scanf("%d",&n);for(int i=1;i<=n;i++) {scanf("%lf%lf",&pos[i][0],&pos[i][1]);set[i]=i;}getchar();for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){char t;t=getchar();if(t=='1'){Pt[i][j]=Pt[j][i]=dis[i][j]=sqrt((pos[i][0]-pos[j][0])*(pos[i][0]-pos[j][0])+(pos[i][1]-pos[j][1])*(pos[i][1]-pos[j][1]));int a=getfather(i),b=getfather(j);if(a!=b) set[a]=b;//并查集}}getchar();}for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){if(Pt[i][j]) continue;//跳过输入处已经计算过得点对elsePt[i][j]=Pt[j][i]=sqrt((pos[i][0]-pos[j][0])*(pos[i][0]-pos[j][0])+(pos[i][1]-pos[j][1])*(pos[i][1]-pos[j][1]));}//预先计算出任意两点间距离for(int k=1;k<=n;k++)for(int i=1;i<=n;i++)for(int j=1;j<=n;j++){if(dis[i][k]==0||dis[k][j]==0) continue;if(i==j) continue;if(dis[i][j]==0||(dis[i][k]+dis[k][j]<dis[i][j])) dis[i][j]=dis[j][i]=dis[i][k]+dis[k][j];}//floyd求各点对最小距离for(int i=1;i<=n;i++){double maxp=0;for(int j=1;j<=n;j++){if(maxp<dis[i][j])maxp=dis[i][j];int a=getfather(i);if(diameter[a]<dis[i][j]) diameter[a]=dis[i][j];}ffar[i]=maxp;}//存储每个连通分支的直径,以及每个点在其连通分支中所能到达的最远距离double r=200000;for(int i=1;i<=n;i++)for(int j=i+1;j<=n;j++){int a=getfather(i),b=getfather(j);if(a==b) continue;double dia=diameter[a]>diameter[b]?diameter[a]:diameter[b];//这里很重要,因为将两个分支连接后ffar[i]+ffar[j]+Pt[i][j]不一定大于原来两个分支各自的直径if((ffar[i]+ffar[j]+Pt[i][j])>dia) dia=ffar[i]+ffar[j]+Pt[i][j];if(dia<r) r=dia;}printf("%.6lf\n",r);return 0;}


 

0 0