poj 1679 The Unique MST

来源:互联网 发布:js获取当前触发事件 编辑:程序博客网 时间:2024/06/18 05:57

题意:给定一个连通的无向图,判断最小生成树是否唯一。


思路:

1.对于图中每条边,把存在相同权值的边作一个标记。

2.然后求出MST。

3.求的MST后如果该MST未包含标记的边,则可判定MST唯一;如果包含了作了标记的边,则一次去掉这些边再求MST,如果求得的MST和原来的MST权值相同,即可判定MST不唯一。


代码:

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int maxn = 105;const int maxm = 5005;struct edge{int u,v;int w;bool equal;//是否存在相等的边 bool used;//第一次构造时是否使用 bool del;//是否删除bool operator < (const edge &b) const{return w < b.w;}};int n,m;edge a[maxm];int p[maxn];bool fg; //是否是第一次构造 void UFset(){for(int i = 0; i <= n; i++)p[i] = -1;}int Find(int x){return p[x] >= 0 ? p[x] = Find(p[x]) : x;}void Union(int r1, int r2){r1 = Find(r1);r2 = Find(r2);int t = p[r1] + p[r2];if(p[r1] > p[r2]){p[r1] = r2;p[r2] = t;}else{p[r2] = r1;p[r1] = t;}}int Kruskal(){int sum = 0;int num = 0;UFset();for(int i = 0; i < m; i++){if(a[i].del)//这条边已经被去除 continue;int u = a[i].u, v = a[i].v;if(Find(u) != Find(v)){Union(u,v);sum += a[i].w;num++;if(fg) a[i].used = true;}if(num >= n-1)break;}return sum;} int main(){int t;//freopen("data.in","r",stdin);//freopen("data.out","w",stdout);cin>>t;while(t--){cin>>n>>m;for(int i = 0; i < m; i++){cin>>a[i].u>>a[i].v>>a[i].w;a[i].del = false;a[i].equal = false;a[i].used = false;}sort(a,a+m);for(int i = 1; i < m; i++){//标记权值相等的边 if(a[i].w == a[i-1].w){a[i].equal = true;a[i-1].equal = true;}}fg = true; int w1 = Kruskal();int w2 = -1;fg = false;for(int i = 0; i < m; i++){if(a[i].used && a[i].equal){a[i].del = true;w2 = Kruskal();if(w1 == w2){cout<<"Not Unique!\n";break;}a[i].del = false;}}if(w1 != w2)cout<<w1<<"\n";}return 0;}


0 0
原创粉丝点击