POJ 3164 Command Network(最小树形图)

链接:http://poj.org/problem?id=3164

本文链接:http://www.cnblogs.com/Ash-ly/p/5532260.html

题意:

  有一个指挥网络被战争破坏了,你的任务是建立一个临时的通信网络.这个网络最重要的的一点是能够把命令传到被摧毁的网络的每个点上,所以要建立一个单向的传输网络.假设所有的传输节点都分别分布在一个平面上.如果命令要想从节点A传送到结点B上,必须建立一条单向电缆从节点A连接到结点B.因为是战争时期,不能任意两个节点之间都要连接,所以让你给出满足要求的通信网络所需要的最少的电缆的长度.

思路:

  电缆的传输信息是单向的,并且命令只要能够传下去就可以,不需要反馈回来.所以可以建立有向图,很显然求得是这个有向图上的最小树形图.这里直接用朱刘算法求最小树形图了.这道题WA了好几次,最后看到一句话"用double时,输入要用%lf输出要用%f".......这题有毒~

代码:

  1 #include <iostream>
  2 #include <cmath>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <algorithm>
  7 #include <string>
  8 #include <queue>
  9 #include <stack>
 10 #include <vector>
 11 #include <map>
 12 typedef long long LL;
 13 using namespace std;
 14 const int MAXV = 100;
 15 const int MAXE = 10000;
 16 const int INF = 0x3f3f3f3f;
 17 
 18 struct Point{
 19     int x;
 20     int y;
 21 }pt[MAXV + 7];
 22 
 23 double zhuliu(int root, int V, double map[MAXV + 7][MAXV + 7]){
 24     bool visited[MAXV + 7];
 25     bool flag[MAXV + 7];
 26     int pre[MAXV + 7];
 27     double sum = 0;
 28     int i, j, k;
 29     for(i = 0; i <= V; i++) flag[i] = false, map[i][i] = INF;
 30     pre[root] = root;
 31     while(true){
 32         for(i = 1; i <= V; i++){
 33             if(flag[i] || i == root) continue;
 34             pre[i] = i;
 35             for(j = 1; j <= V; j++)
 36                 if(!flag[j] && map[j][i] < map[pre[i]][i])
 37                     pre[i] = j;
 38             if(pre[i] == i) return -1;
 39         }
 40         for(i = 1; i <= V; i++){
 41             if(flag[i] || i == root) continue;
 42             for(j = 1; j <= V; j++) visited[j] = false;
 43             visited[root] = true;
 44             j = i;
 45             do{
 46                 visited[j] = true;
 47                 j = pre[j];
 48             }while(!visited[j]);
 49             if(j != i)continue;
 50             i = j;
 51             do{
 52                 sum += map[pre[j]][j];
 53                 j = pre[j];
 54             }while(j != i);
 55             j = i;
 56             do{
 57                 for(k = 1; k <= V; k++)
 58                     if(!flag[k] && map[k][j] < INF && k != pre[j])
 59                         map[k][j] -= map[pre[j]][j];
 60                 j = pre[j];
 61             }while(j != i);
 62             for(j = 1; j <= V; j++){
 63                 if(j == i) continue;
 64                 for(k = pre[i]; k != i; k = pre[k]){
 65                     if(map[k][j] < map[i][j]) map[i][j] = map[k][j];
 66                     if(map[j][k] < map[j][i]) map[j][i] = map[j][k];
 67                 }
 68             }
 69             for(j = pre[i]; j != i; j = pre[j]) flag[j] = true;
 70             break;
 71         }
 72         if(i > V){
 73             for(i = 1; i <= V; i++)
 74                 if(!flag[i] && i != root) sum += map[pre[i]][i];
 75             break;
 76         }
 77     }
 78     return sum;
 79 }
 80 
 81 double dist(struct Point a, struct Point b)
 82 {
 83     return hypot(a.x - b.x, a.y - b.y);
 84 }
 85 
 86 int main()
 87 {
 88     //freopen("input.txt", "r", stdin);
 89     int n, m;
 90     while(~scanf("%d%d", &n, &m)){
 91         double map[MAXV + 7][MAXV + 7] = {0};
 92         for(int i = 0; i <= n; i++) for(int j = 0; j <= n; j++) map[i][j] = INF;
 93         memset(&pt, 0, sizeof(Point));
 94         for(int i = 1; i <= n; i++) scanf("%d%d", &pt[i].x, &pt[i].y);
 95         for(int i = 0; i < m; i++){
 96             int u, v;
 97             scanf("%d%d", &u, &v);
 98             map[u][v] = dist(pt[u], pt[v]);
 99         }
100         double ans = zhuliu(1, n, map);
101         if(ans != -1)    printf("%.2f\n", ans);
102         else printf("poor snoopy\n");
103     }
104     return 0;
105 }

 

 

posted @ 2016-05-26 18:40  vrsashly  阅读(341)  评论(0编辑  收藏  举报