思路是先找出最小生成树,并记录每条遍,要想说明是唯一的最小生成树,那么他的每条边都是必不可少的,然后我们可以枚举所有最小生成树的边 ,依次去掉,看是否还能不能组成一棵相同权值和的mst。就是因为当初的一点点儿错误导致 ,一周了将近,才拿出来,一眼看出bug!
#include<iostream> #include<string.h> #include<queue> #include<algorithm> using namespace std; const int M=103; int F[M]; int r[M]; int n,m,t,cnt; int res,ans; struct edge { int u,v,w; } per[M*M*M]; bool cmp(edge a,edge b) { return a.w<b.w; } void init() { for(int i=1; i<=n; i++) { F[i]=i; r[i]=1; } } //int Find(int x) //{ // if(x!=F[x]) // F[x]=Find(F[x]); // return F[x]; //} int Find(int x) { int r=x; while(r!=F[r]) { r=F[r]; } int k=x; while(k!=r) { int t=F[k]; F[k]=r; k=t; } return r; } bool union_set(int u,int v) { int tx=Find(u); int ty=Find(v); if(tx==ty) return false; else if(r[tx]>r[ty]) F[ty]=tx; else if(r[tx]<r[ty]) F[tx]=ty; else { F[tx]=ty; r[ty]++; } return true; } int main() { cin>>t; while(t--) { cin>>n>>m; queue<int>dict; for(int i=0; i<m; i++) cin>>per[i].u>>per[i].v>>per[i].w; sort(per,per+m,cmp); init(); cnt=0; res=0; for(int i=0; i<m; i++) { if(union_set(per[i].u,per[i].v)) { cnt++; dict.push(i); res+=per[i].w; if(cnt==n-1) break; } } int flag=0; while(!dict.empty()) { cnt=0; ans=0; init(); int k=dict.front(); dict.pop(); for(int i=0; i<m; i++) { if(i==k) continue; if(union_set(per[i].u,per[i].v)) { cnt++; ans+=per[i].w; if(cnt==n-1) { if(ans==res) { flag=1; break; } } } } if(flag) { cout<<"Not Unique!"<<endl; break; } } if(!flag) cout<<res<<endl; } return 0; }
时间: 2024-11-10 08:21:28