USACO 2.4 Cow Tours(图论乱搞)

这个题意真心看不懂,看了一下翻译,看了好一会汉语的,终于理解了。

给一个图,可能有几个联通的集合,问加上一条边,使得两个集合联通变为一个集合,使得这个集合的点的之间的最短路中的最大的那一条最短。

开始YY一下是否贪心,好像不是,感觉用到了求次小生成树的思想之类的。YY了一个算法,搞了一数组d[i],来记录i所在集合,距离i最远的距离,然后枚举加的边是(i,j)。复杂度应该没什么问题,然后提交,挂了,有点怀疑算法的正确性了,不过还好,想到还要和原来的最短路里边的最长路进行判断,又写了个DFS,AC了。

  1 /*
  2   ID: cuizhe
  3   LANG: C++
  4   TASK: cowtour
  5 */
  6 #include <iostream>
  7 #include <cstdio>
  8 #include <cstring>
  9 #include <cmath>
 10 #include <algorithm>
 11 using namespace std;
 12 #define N 1e10
 13 #define eps 1e-8
 14 int x[201],y[201];
 15 char str[201][201];
 16 int o[201],n;
 17 double p[201][201],d[201],dis[201][201],Max[201];
 18 double mm;
 19 void dfs(int x)//求所在集合里的最长路
 20 {
 21     int i;
 22     o[x] = 1;
 23     for(i = 1;i <= n;i ++)
 24     {
 25         if(p[x][i] != N)
 26         {
 27             if(mm < p[x][i])
 28             mm = p[x][i];
 29             if(!o[i]) dfs(i);
 30         }
 31     }
 32     Max[x] = mm;
 33 }
 34 int main()
 35 {
 36     int i,j,k;
 37     freopen("cowtour.in","r",stdin);
 38     freopen("cowtour.out","w",stdout);
 39     scanf("%d",&n);
 40     for(i = 1;i <= n;i ++)
 41     scanf("%d%d",&x[i],&y[i]);
 42     for(i = 0;i <= n-1;i ++)
 43     {
 44         scanf("%s",str[i]);
 45     }
 46     for(i = 1;i <= n;i ++)
 47     {
 48         for(j = 1;j <= n;j ++)
 49         {
 50             dis[i][j] = sqrt((x[i]-x[j])*(x[i]-x[j])*1.0+(y[i]-y[j])*(y[i]-y[j])*1.0);
 51         }
 52     }
 53     for(i = 0;i <= n-1;i ++)//初始化
 54     {
 55         for(j = 0;j <= n-1;j ++)
 56         {
 57             if(str[i][j] == '1')
 58             p[i+1][j+1] = dis[i+1][j+1];
 59             else
 60             p[i+1][j+1] = N;
 61         }
 62         p[i+1][i+1] = 0;
 63     }
 64     for(i = 1;i <= n;i ++)//FLOYD求最短路
 65     {
 66         for(j = 1;j <= n;j ++)
 67         {
 68             for(k = 1;k <= n;k ++)
 69             {
 70                 if(p[j][k] > p[j][i]+p[i][k])
 71                 p[j][k] = p[j][i]+p[i][k];
 72             }
 73         }
 74     }
 75     for(i = 1;i <= n;i ++)
 76     {
 77         mm = 0;
 78         if(!o[i]) dfs(i);
 79     }
 80     double ans = 0;
 81     for(i = 1;i <= n;i ++)//找离i联通且距离最大的距离
 82     {
 83        d[i] = -N;
 84        for(j = 1;j <= n;j ++)
 85        {
 86            if(p[i][j] != N&&d[i] < p[i][j])
 87            {
 88                d[i] = p[i][j];
 89            }
 90        }
 91     }
 92     ans = N;
 93     for(i = 1;i <= n;i ++)
 94     {
 95         for(j = 1;j <= n;j ++)
 96         {
 97             if(p[i][j] == N)
 98             {
 99                 if(ans > max(dis[i][j]+d[i]+d[j],max(Max[i],Max[j])))
100                 ans = max(dis[i][j]+d[i]+d[j],max(Max[i],Max[j]));
101             }
102         }
103     }
104     printf("%.6lf\n",ans+eps);
105     return 0;
106 }
posted @ 2012-11-15 12:33  Naix_x  阅读(1523)  评论(0编辑  收藏  举报