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 }