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 }

你可能感兴趣的:(USACO)