MST一道经典变形题目。问你MST是否唯一。
MST的权是唯一的,但MST不一定唯一。
MST不唯一的必要条件之一是无向网有相同权值的边。
即,MST不唯一,无向网一定有相同权值的边,但是无向网有相同权值的边,MST不一定唯一。
得到一个逆否命题,MST没有使用无向网中相同权值的边,那么MST一定唯一。
如果MST使用了无向图中相同权值的边,那么依次去掉这些边,如果某次去掉之后得到MST的权与最初的MST权是相等的则说明MST不唯一。否则说明唯一。1
标记所有存在相同权值的边。
Kruskal求MST,标记使用过的存在相同权值的边。如果没用使用过相同权值的边,则说明唯一。
否则,依次删除掉被标记的使用过的相同权值的边,如果所得MST与第一次得到的权相等则说明不唯一。
#include <iostream> #include <string> #include <cstdlib> #include <cstring> #include <cstdio> #include <algorithm> #define MAXN 105 using namespace std; struct Edge { int a,b,weight; bool equl,used,dele; Edge():equl(0),used(0),dele(0) {} }; Edge e[MAXN*MAXN]; int father[MAXN]; bool fir,uq; bool cmp(Edge a,Edge b) { return a.weight<b.weight; } int find(int p) { return p==father[p]?p:(father[p]=find(father[p])); } void Init(int n) { for(int i=0; i<=n; ++i) father[i]=i; } int Kruskal(int n,int m) { Init(n); sort(e,e+m,cmp); int ans=0; for(int i=0; i<m; ++i) { if(e[i].dele) continue; int ta=find(e[i].a),tb=find(e[i].b),val=e[i].weight; if(ta!=tb) { father[ta]=tb; ans+=val; if(fir&&e[i].equl) { e[i].used=true; uq=false; } } } return ans; } int main() { int T; scanf("%d",&T); while(T--) { int n,m; scanf("%d%d",&n,&m); for(int i=0; i<m; ++i) { scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].weight); e[i].equl=e[i].used=e[i].dele=false; } if(m==1) { printf("%d\n",e[0].weight); continue; } sort(e,e+m,cmp); for(int i=1; i<m; ++i) { if(e[i].weight==e[i-1].weight) e[i].equl=e[i-1].equl=true; } uq=true; fir=true; int ans=Kruskal(n,m); if(uq) { printf("%d\n",ans); continue; } fir=false; for(int i=0; i<m; ++i) { if(!e[i].used) continue; e[i].dele=true; int res=Kruskal(n,m); if(res==ans) { uq=false; break; } else uq=true; e[i].dele=false; } if(uq) printf("%d\n",ans); else puts("Not Unique!"); } return 0; }