首页 > 其他 > 详细

POJ 1679 判最小生成树的不唯一性

时间:2015-03-24 10:52:56      阅读:249      评论:0      收藏:0      [点我收藏+]

题目大意:

给定一个无向图,寻找它的最小生成树,如果仅有一种最小生成树,输出所有边的和,否则输出unique!

 

根据kruscal原理来说,每次不断取尽可能小的边不断添加入最小生成树中,那么可知如果所有边的长度都不相同,那么kruscal取得过程必然只有一种情况,由小到大

所以要是存在多种情况的最小生成树,那么必然是存在相同的边

初始将所有相同的边进行标记,生成第一次最小生成树后,不断去除其中带标记的边,然后再计算最小生成树,判断能否得到同样的答案,如果可以,说明不止一种情况

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 #define N 105
 6 int fa[N] , same[N] , first[N] , k;
 7 int rec[N] , amo;//rec[]记录MST中含有相同长度边的位置,amo记录其数量
 8 struct Edge{
 9     int x,y,d,next,flag;
10     bool same;
11     bool operator<(const Edge &m) const{
12         return d<m.d;
13     }
14 }e[N*N];
15 
16 int find_head(int x)
17 {
18     while(fa[x]!=x) x=fa[x];
19     return x;
20 }
21 
22 bool Union(int x,int y)
23 {
24     int fa_x = find_head(x);
25     int fa_y = find_head(y);
26     fa[fa_x] = fa_y;
27     return fa_x == fa_y;
28 }
29 
30 void add_edge(int x, int y , int d)
31 {
32     e[k].x=x , e[k].y=y , e[k].d=d , e[k].flag=1 , e[k].next=first[x];
33     e[k].same = false;
34     first[x] = k++;
35 }
36 
37 int cal_MST(int n , int flag)
38 {
39     int ans = 0 , cnt=0;
40     for(int i=1 ; i<=n ; i++) fa[i]=i;
41     for(int i=0 ; i<k ; i++){
42         if(e[i].flag==1){
43             if(!Union(e[i].x , e[i].y)){
44                 ans+=e[i].d;
45                 if(e[i].same && flag){
46                     rec[amo++] = i;
47                 }
48                 cnt++;
49                 if(cnt == n-1) break;
50             }
51         }
52     }
53     return ans;
54 }
55 
56 int main()
57 {
58     int T;
59     scanf("%d" , &T);
60     while(T--)
61     {
62         int n , m , x , y , d;
63         scanf("%d%d" , &n , &m);
64         k=0;
65         memset(first , -1 , sizeof(first));
66         for(int i=0 ; i<m ; i++){
67             scanf("%d%d%d" , &x , &y , &d);
68             add_edge(x , y , d);
69         }
70 
71         sort(e , e+k);
72         //对存在相同边的边进行标记
73         for(int i=1 ; i<k ; i++)
74             if(e[i].d == e[i-1].d) e[i].same=e[i-1].same=true;
75         amo = 0;
76         int ans = cal_MST(n , 1);
77         bool is_unique = true;
78         for(int i=0 ; i<amo ; i++){
79             e[rec[i]].flag = 0;
80             int t=cal_MST(n , 0);
81             if(t == ans){
82                 is_unique=false;
83                 break;
84             }
85             e[rec[i]].flag = 1;
86         }
87         if(is_unique) printf("%d\n" , ans);
88         else puts("Not Unique!");
89     }
90     return 0;
91 }

 

POJ 1679 判最小生成树的不唯一性

原文:http://www.cnblogs.com/CSU3901130321/p/4361988.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!