题意: 判断最小生成树是否唯一,唯一则输出最小生成数的所有边之和,否则输出 NO。。。
用两遍kruskal ,如果有大小相同的边,第一次则选择序号小的,第二次选择序号大的。如果两次生成的树相同,则是唯一的最小生成树。
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <queue> using namespace std; const int N = 109; const int M = 10009; struct LL{ int f,t,dis,i; } L[M]; bool cmp1(LL a,LL b) { if(a.dis==b.dis) return a.i<b.i; return a.dis<b.dis; } bool cmp2(LL a,LL b) { if(a.dis==b.dis) return a.i>b.i; return a.dis<b.dis; } int n,m; void init() { scanf("%d%d",&n,&m); int f,t,d; for(int i=0;i<m;i++) { scanf("%d%d%d",&f,&t,&d); L[i].dis = d; L[i].f = f; L[i].t = t; L[i].i = i; } } int fa[N]; int fin_fa(int k) { if(fa[k]==k) return k; return fa[k] = fin_fa(fa[k]); } void un(int f,int t) { fa[fin_fa(f)] = fin_fa(t); } bool map[N][N]; void solve() { memset(map,false,sizeof(map)); int s = 1,ans=0; for(int i=0;i<=n;i++) fa[i] = i; sort(L,L+m,cmp1); for(int i=0;i<m;i++) { if(fin_fa(L[i].f)!=fin_fa(L[i].t)) { s++; un(L[i].f,L[i].t); map[L[i].f][L[i].t] = map[L[i].t][L[i].f] = true; //cout<<L[i].f<<" in "<<L[i].t<<endl; ans+=L[i].dis; } } if(s<n) { printf("Not Unique!\n"); return ; } sort(L,L+m,cmp2); for(int i=0;i<=n;i++) fa[i] = i; for(int i=0;i<m;i++) { if(fin_fa(L[i].f)!=fin_fa(L[i].t)) { s++; un(L[i].f,L[i].t); // cout<<L[i].f<<" out "<<L[i].t<<endl; if(!map[L[i].f][L[i].t]) { printf("Not Unique!\n"); return ; } } } printf("%d\n",ans); } int main() { freopen("in.txt","r",stdin); int cas; scanf("%d",&cas); while(cas--) { init(); solve(); } return 0; }