题目链接:
http://poj.org/problem?id=1679
解题思路:
1.首先求出原图的最小生成树,并将此生成树的每条边作标记;
2.每次只删除其中一条边,再求最小生成树,观察结果与最开始的是否一致,是则不唯一;
3.当所有被标记的边都被删过一次后,如果没有一次结果与最开始的一致,则是唯一的。
AC代码:
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; int n,m; struct Edge { int u,v,w; int flag; }edge[100005]; int pa[110]; int del[110]; bool cmp(Edge a,Edge b) { return a.w < b.w; } void init(){ for(int i = 1; i <= n; i++) pa[i] = i; } int findset(int x) { if(pa[x] != x) pa[x] = findset(pa[x]); return pa[x]; } int kruskal(int dell) { int i,u,v,cnt = n,sum = 0; for(i = 0; i < m; i++) { if(i == dell) continue; u = findset(edge[i].u); v = findset(edge[i].v); if(u != v) { sum += edge[i].w; pa[v] = u; edge[i].flag = 1; if(--cnt == 1) break; } } return sum; } int main(){ int T; scanf("%d",&T); while(T--){ scanf("%d%d",&n,&m); int u,v,w; for(int i = 0; i < m; i++){ scanf("%d%d%d",&u,&v,&w); edge[i].u = u; edge[i].v = v; edge[i].w = w; edge[i].flag = 0; } sort(edge,edge+m,cmp); int ans,ans1,tmp = 0,k = 0; init(); ans = kruskal(-1); for(int i = 1; i <= n; i++) if(pa[i] == i) tmp++; if(tmp > 1){ printf("0\n"); continue; } for(int i = 0; i < m; i++) if(edge[i].flag) del[k++] = i; int flag = 0; for(int i = 0; i < k; i++){ init(); ans1 = kruskal(del[i]); tmp = 0; for(int j = 1; j <= n; j++) if(pa[i] == i) tmp++; if(tmp > 1) continue; if(ans1 == ans){ flag = 1; break; } } if(flag) printf("Not Unique!\n"); else printf("%d\n",ans); } return 0; }