(最小生成树唯一性)POJ 1679

题意:

给定一个无向带权图,判断这个图是否有唯一的最小生成树,如果有输出最小生成树,否则输出Not Unique!


分析:

模板题,但是对于判断唯一性,有一定的小技巧,先算出整个图的最小生成树,记录这个最小生成树的所有边,然后在整个图中枚举把之前最小生成树删掉一条边,再求最小生成树,一旦出现相同的总权值,就不行了。

然后Kruskal算法反正很快,我发现最小生成树的解决方案往往很暴力,2333。很强


代码:

  1 #include <set>
  2 #include <map>
  3 #include <list>
  4 #include <cmath>
  5 #include <queue>
  6 #include <stack>
  7 #include <vector>
  8 #include <bitset>
  9 #include <string>
 10 #include <cctype>
 11 #include <cstdio>
 12 #include <cstring>
 13 #include <cstdlib>
 14 #include <iostream>
 15 #include <algorithm>
 16 // #include <unordered_map>
 17 
 18 using namespace std;
 19 
 20 typedef long long ll;
 21 typedef unsigned long long ull;
 22 typedef pair<int, int> pii;
 23 typedef pair<ull, ull> puu;
 24 
 25 #define inf (0x3f3f3f3f)
 26 #define lnf (0x3f3f3f3f3f3f3f3f)
 27 #define eps (1e-9)
 28 #define fi first
 29 #define se second
 30 
 31 bool sgn(double a, string select, double b) {
 32     if(select == "==")return fabs(a - b) < eps;
 33     if(select == "!=")return fabs(a - b) > eps;
 34     if(select == "<")return a - b < -eps;
 35     if(select == "<=")return a - b < eps;
 36     if(select == ">")return a - b > eps;
 37     if(select == ">=")return a - b > -eps;
 38 }
 39 
 40 
 41 //--------------------------
 42 
 43 const ll mod = 1000000007;
 44 const int maxn = 110;
 45 
 46 
 47 int n,m;
 48 
 49 int par[maxn];
 50 
 51 struct Edge {
 52     int u,v,w;
 53 } edge[maxn*maxn];
 54 
 55 vector<int> mstedge;
 56 
 57 bool cmp(Edge a,Edge b) {
 58     return a.w<b.w;
 59 }
 60 
 61 int findx(int x) {
 62     if(par[x]==x)return x;
 63     else return par[x]=findx(par[x]);
 64 }
 65 
 66 
 67 int Kruskal(int n,int x) {
 68     for(int i=1; i<=n; i++) {
 69         par[i]=i;
 70     }
 71     int cnt=0;
 72     int ans=0;
 73     for(int i=0; i<m; i++) {
 74         if(i==x)continue;
 75         int u = edge[i].u;
 76         int v = edge[i].v;
 77         int w = edge[i].w;
 78         int t1 = findx(u);
 79         int t2 = findx(v);
 80         if(t1!=t2) {
 81             ans+=w;
 82             par[t1]=t2;
 83             cnt++;
 84             if(x==-1)mstedge.push_back(i);
 85         }
 86         if(cnt==n-1)break;
 87     }
 88     if(cnt<n-1)return -1;
 89     else return ans;
 90 }
 91 
 92 void solve() {
 93     int t;
 94     scanf("%d",&t);
 95     while(t--) {
 96         memset(edge,0,sizeof(edge));
 97         mstedge.clear();
 98         scanf("%d%d",&n,&m);
 99         for(int i=0; i<m; i++) {
100             scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
101         }
102         sort(edge,edge+m,cmp);
103         int res = Kruskal(n,-1);
104 //        printf("res=%d
",res);
105         bool same = false;
106         for(int i=0; i<mstedge.size(); i++) {
107             int rr = Kruskal(n,mstedge[i]);
108 //            printf("rr=%d
",rr);
109             if(rr==res) {
110                 puts("Not Unique!");
111                 same=true;
112                 break;
113             }
114         }
115         if(!same) {
116             printf("%d
",res);
117         }
118     }
119 }
120 
121 int main() {
122 
123 #ifndef ONLINE_JUDGE
124     freopen("1.in", "r", stdin);
125     // freopen("1.out", "w", stdout);
126 #endif
127     // iostream::sync_with_stdio(false);
128     solve();
129     return 0;
130 }
原文地址:https://www.cnblogs.com/tak-fate/p/6665253.html