USACO Cow Tours 题解

本文介绍了一种通过连接两个不连通的分量来最小化图直径的算法。使用Floyd算法预处理各分量内节点间的最远距离,并通过枚举找出最优连接方式。

         题目大意如下:给定一个无向图,该图由两个或两个以上的联通分量构成,每个联通分量的直径定义为图中相距最远的两个点的距离;图的直径定义为图中所有联通分量直径的最大值。那么,如果再绘制一条连接两个联通分量的边,怎样使得最后的图的直径最小?

算法如下:

1、  Floyd算法求出各个联通分量中任意两顶点ij之间的距离dist[i][j],则此时的图的直径r1为所有点对之间的最大距离

2、  对于每个顶点i,求出距离它最远的点的距离len[i]

3、  最后,枚举所有不联通的点ij,两者之间连接一条线,并且此时的新的距离为len[i]+len[j]+dist[i][j],并且令r2为这些距离中最大距离

4、  那么最终的直径为max(r1,r2)

  1. /*
  2. ID: millky
  3. PROG: cowtour
  4. LANG: C++
  5. */
  6. #include <iostream>
  7. #include <fstream>
  8. #include <string>
  9. #include <cmath>
  10. #include <algorithm>
  11. #include <vector>
  12. #include<iomanip>
  13. using namespace std;
  14. ifstream fin("cowtour.in");
  15. ofstream fout("cowtour.out");
  16. #define sqare(x) (x)*(x)
  17. struct point{int x,y;};
  18. int N;
  19. const double maxD = 1000000000.0;
  20. point co[150];
  21. double dist[150][150],lft[150],best[150][150];
  22. int res=-1;
  23. double getDist(int i,int j)
  24. {
  25.     return sqrt((double)sqare(co[i].x-co[j].x)+(double)sqare(co[i].y-co[j].y));
  26. }
  27. void init()
  28. {
  29.     fin>>N;
  30.     string temp;
  31.     for (int i=0;i<N;++i)fin>>co[i].x>>co[i].y;
  32.     for (int i=0;i<N;++i) lft[i]=0;
  33.     for (int i=0;i<N;++i) for(int j=0;j<N;++j)
  34.     {
  35.         dist[i][j]=maxD;
  36.         best[i][j]=getDist(i,j);
  37.     }
  38.     for (int i=0;i<N;++i)
  39.     {
  40.         fin>>temp;
  41.         for (int j=0;j<i;++j)
  42.             if(temp[j]!='0'
  43.                 dist[i][j]=dist[j][i]=best[i][j];
  44.     }
  45. }
  46. void floyd()
  47. {
  48.     for (int k=0;k<N;++k)
  49.         for (int i=0;i<N;++i)
  50.             for (int j=0;j<N;++j)
  51.                 if(i!=j)dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);
  52.     for (int i=0;i<N;++i)
  53.         for (int j=0;j<N;++j)
  54.             if (dist[i][j]<maxD) lft[i]=max(lft[i],dist[i][j]);
  55. }
  56. double getRes()
  57. {
  58.     double res=maxD;
  59.     for (int i=0;i<N;++i)
  60.         for (int j=0;j<i;++j)
  61.             if (i!=j && dist[i][j]==maxD)res = min(res,lft[i]+lft[j]+best[i][j]);
  62.     return max(res,*max_element(lft,lft+N));
  63. }
  64. int main()
  65. {
  66.     init();
  67.     floyd();
  68.     fout.setf(ios::fixed);
  69.     fout<<setprecision(6)<<getRes()<<endl;
  70.     return 0;
  71. }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值