POJ 1679 The Unique MST(判断最小生成树是否唯一)
2016-04-04 14:02
591 查看
题目链接:POJ 1679 The Unique MST
POJ 1679 The Unique MST(判断最小生成树是否唯一)思路:枚举删边,再求最小生成树,相等则不唯一
判断最下生成树是否唯一的思路一:1、对图中的每一条边,扫描其他边,如果存在相同权值的边,则对该边做标记。
2、然后用Kruskal算法或Prim算法求MST。
3、求得MST后,如果该MST中未包含做了标记的边,即可判断MST唯一;如果包含做了标记的边,则依次去掉这些边再求MST,如果求得的MST权值和原来的MST的权值一样,即可判断MST不唯一。
判断最下生成树是否唯一的思路二:(较为复杂)
首先求出原图最小生成树,权值之和为min 枚举添加每条不在最小生成树上的边 ,加上以后一定会形成一个环。
找到环上除了(u,v)以外的权值最大的边,把它删掉,计算当前生成树的权值之和。 枚举完所有边之后,得到的最小值即为次小生成树的权值。
具体实现时,更简单的方法是从每个节点i遍历整个最小生成树
定义F[i][j]为在生成树上,从i到j的路径上最大的边的权值。通过BFS,求出F[i][j]的值
然后对于添加每条不在最小生成树中的边(i,j),并删去该环中的原生成树的的最大边。 新的生成树权值之和就是Min + w(i,j) –
F[i][j] 记录其最小值,则为次小生成树。
次小生成树详解点这里
鄙人愚钝,用的删边枚举:
当且仅当第i条边与第j条边的权值相等,且MST中包含第i条边时,删去第i条边,再求MST.可以减掉多次枚举
/************************************************************************* > File Name: poj_1679.cpp > Author: dulun > Mail: dulun@xiyoulinux.org > Created Time: 2016年04月03日 星期日 17时38分34秒 ************************************************************************/ #include<iostream> #include<stdio.h> #include<cstring> #include<cstdlib> #include<algorithm> #define LL long long using namespace std; const int N = 50086; bool first = 0; int n, m; int p ; struct Edge { int s, e, w; bool same, use, del; }; Edge e ; bool cmp(Edge a, Edge b) { return a.w < b.w; } int find(int x) { return x == p[x] ? x : p[x] = find(p[x]); } void init() { for(int i = 0; i < N; i++) p[i] = i; } int kruscal() { int cnt = 0, ans = 0; init(); for(int i = 0; i < m; i++) { if(e[i].del == true) continue; int x = find(e[i].s); int y = find(e[i].e); if( x!=y ) { p[x] = y; ans+=e[i].w; if(first) e[i].use = true; cnt++; } if(cnt == n-1) return ans; } return ans; } void findSameWeight() { for(int i = 0; i < m; i++) for(int j = 0; j < m; j++) { if(i==j) continue; if(e[i].w == e[j].w) e[i].same = true; } } void sovle() { sort(e, e+m, cmp); first = true; int ans_MST = kruscal(); first = false; for(int i = 0; i < m; i++) { if(e[i].use && e[i].same) { e[i].del = true; int ans = kruscal(); e[i].del = false; if(ans == ans_MST) { printf("Not Unique!\n"); return ; } } } printf("%d\n", ans_MST); return; } int main() { int t; cin>>t; while(t--) { scanf("%d%d", &n, &m); for(int i = 0; i < m; i++) { int a, b, w; scanf("%d%d%d", &a, &b, &w); e[i].s = a, e[i].e = b, e[i].w = w; e[i].same = false; e[i].use = false; e[i].del = false; } findSameWeight(); sovle(); } return 0; }
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析
- C++实现汉诺塔算法经典实例
- PHP实现克鲁斯卡尔算法实例解析