ACM/ICPC 之 判别MST唯一性-Kruskal解法(POJ1679)

判别MST是否唯一的例题。

 

 

 

POJ1679-The Unique MST

 

  题意:给定图,求MST(最小生成树)是否唯一,唯一输出路径长,否则输出Not Unique!

  题解:MST是否唯一取决于是否有两边权值相同(其中一条边在第一次求得的MST内,另一条在MST外)的情况。

     如果存在这样的边,则需要逐次删除MST内的该边,再次求MST,如果此次求得的MST路长与第一次MST相同,则确实存在不唯一的MST

     否则,一定不存在多条MST。

 

  1 //Kruskal-判断MST是否唯一
  2 //Time:0MS    Memory:868K
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdio>
  6 #include<algorithm>
  7 using namespace std;
  8 
  9 #define MAX 101
 10 
 11 struct Edge {
 12     int u, v;
 13     int w;
 14     bool used;    //First Used
 15     bool del;    //Kruskal是否不考虑此边
 16     friend bool operator < (Edge e1, Edge e2) { return e1.w < e2.w; }
 17 }e[MAX*MAX];
 18 
 19 int n, m;
 20 bool first;    //是否第一次求MST
 21 int fa[MAX];
 22 int del[MAX*MAX], len;    //须逐次删除的边
 23 int minroad;    //第一次MST结果
 24 
 25 int Find(int x)
 26 {
 27     return fa[x] < 0 ? x : fa[x] = Find(fa[x]);
 28 }
 29 
 30 void Union(int r1, int r2)
 31 {
 32     r1 = Find(r1);
 33     r2 = Find(r2);
 34     int num = fa[r1] + fa[r2];
 35     if (fa[r1] < fa[r2])
 36     {
 37         fa[r2] = r1;
 38         fa[r1] = num;
 39     }
 40     else {
 41         fa[r1] = r2;
 42         fa[r2] = num;
 43     }
 44 }
 45 
 46 bool kruskal()
 47 {
 48     memset(fa, -1, sizeof(fa));
 49     int num = 0;
 50     int mind = 0;
 51     for (int i = 0; i < m; i++)
 52     {
 53         if (e[i].del)    continue;
 54         if (Find(e[i].u) == Find(e[i].v))    continue;
 55         Union(e[i].u, e[i].v);
 56         if (first) {
 57             minroad += e[i].w;
 58             e[i].used = true;
 59         }
 60         mind += e[i].w;
 61         if (mind > minroad) return true;
 62         if (++num == n - 1) break;
 63     }
 64     
 65     return false;
 66 }
 67 
 68 int main()
 69 {
 70     int T;
 71     scanf("%d", &T);
 72     while (T--)
 73     {
 74         scanf("%d%d", &n, &m);
 75         memset(e, 0, sizeof(e));
 76         for (int i = 0; i < m; i++)
 77             scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);
 78 
 79         len = 0;
 80         sort(e, e + m);
 81         for (int i = 0; i < m; i++)
 82             if (e[i].w == e[i + 1].w)
 83             {
 84                 if(del[len-1] != i) del[len++] = i;
 85                 del[len++] = i + 1;
 86             }
 87         
 88         minroad = 0;
 89         first = true;
 90         kruskal();
 91         first = false;
 92 
 93         bool unique = true;
 94         for (int i = 0; i < len; i++)
 95         {
 96             if (!e[del[i]].used) continue;    //使用过的才删除
 97             e[del[i]].del = true;    //删除
 98             if (!kruskal())
 99             {
100                 printf("Not Unique!\n");
101                 unique = false; break;
102             }
103             e[del[i]].del = false;    //恢复
104         }
105 
106         if (unique)
107             printf("%d\n", minroad);
108     }
109 
110 
111 
112     return 0;
113 }

 

    原文作者:Inkblots
    原文地址: https://www.cnblogs.com/Inkblots/p/5390767.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞