POJ1679判断最小生成树是否唯一

判断最小生成树是否唯一的思路:
  (1) 对图中每条边,扫描其它边,如果存在权值相同的边,则对该边作标记
  (2) 然后用Kruskal算法求MST
  (3) 求得MST后,如果该MST中为包含作了标记的边,即可判定MST唯一;
       如果包含作了标记的边,则依次去掉这些边再求MST,如果求得的MST
       权值与原MST的权值相同,即可判定MST不唯一

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 using namespace std;
  7 #define N 105
  8 #define M 10050
  9 struct Edge
 10 {
 11     int u,v,w;
 12     int equal;
 13     int del;
 14     int used;
 15 }edge[M];
 16 int father[N],rank[N];
 17 int n,m;
 18 bool first;
 19 
 20 bool cmp(Edge a,Edge b)
 21 {
 22     return a.w < b.w ;
 23 }
 24 
 25 void Init()
 26 {
 27     for(int i=1; i<=n; i++)
 28     {
 29         rank[i] = 1;
 30         father[i] = i;
 31     }
 32 }
 33 
 34 int find(int x)
 35 {
 36     if(father[x] != x)
 37     father[x] = find(father[x]);
 38     return father[x];
 39 }
 40 
 41 void merge(int x,int y)
 42 {
 43     int xf = find(x);
 44     int yf = find(y);
 45     if(rank[xf] > rank[yf])
 46     {
 47         rank[xf] += rank[yf];
 48         father[yf] = xf;
 49     }
 50     else
 51     {
 52         rank[yf] += rank[xf];
 53         father[xf] = yf;
 54     }
 55 }
 56 
 57 int Kruskal()
 58 {
 59     int num = 0;
 60     int sum = 0;
 61     Init();
 62     for(int i=0; i<m; i++)
 63     {
 64         int u = edge[i].u ;
 65         int v = edge[i].v ;
 66         if(edge[i].del) continue;
 67         if(find(u) != find(v))
 68         {
 69             num++;
 70             sum += edge[i].w;
 71             merge(u,v);
 72             if(first) edge[i].used = 1;
 73         }
 74         if(num==n-1) break;
 75     }
 76     if(num<n-1) return -1;
 77     return sum;
 78 }
 79 
 80 int main()
 81 {
 82     int T;
 83     int u,v,w;
 84     scanf("%d",&T);
 85     while(T--)
 86     {
 87         scanf("%d%d",&n,&m);
 88         for(int i=0; i<m; i++)
 89         {
 90             scanf("%d%d%d",&u,&v,&w);
 91             edge[i].u = u ; edge[i].v = v ; edge[i].w = w ;
 92             edge[i].equal = 0 ; edge[i].del = 0 ; edge[i].used = 0 ;
 93         }
 94         for(int i=0; i<m; i++)
 95         for(int j=i+1; j<m; j++)
 96         {
 97             if(edge[i].w == edge[j].w)
 98             edge[i].equal = edge[j].equal = 1;
 99         }
100         sort(edge,edge+m,cmp);
101         first = 1;
102         int sum1 = Kruskal();
103         int flag = 1;
104         first = 0;
105         for(int i=0; i<m; i++)
106         {
107             if(edge[i].used && edge[i].equal)
108             {
109                 edge[i].del = 1;
110                 int sum2 = Kruskal();
111                 if(sum1 == sum2)
112                 {
113                     printf("Not Unique!\n");
114                     flag = 0;
115                     break;
116                 }
117                 edge[i].del = 0;
118             }
119         }
120         if(flag) printf("%d\n",sum1);
121     }
122     return 0;
123 }
View Code

 

posted on 2013-07-31 11:39  爱∪  阅读(160)  评论(0编辑  收藏  举报

导航