http://acm.hust.edu.cn/vjudge/contest/121380#problem/J
题意:判断最小生成树是否唯一。
分析:求其最小生成树,如果最小生成树的长度与次小生成树的长度相等,则不唯一,否则唯一。

#include<algorithm> #include<stdio.h> #include<string.h> #include<queue> using namespace std; const int maxn = 105; const int oo = 0x7fffffff; int path[maxn][maxn], use[maxn][maxn], v[maxn], maps[maxn][maxn], dist[maxn], pre[maxn]; ///path记录两点之间的最大边值,use记录是否是最小生成树上面的边 int n, m; void Init() { for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) maps[i][j] = (i==j ? 0 : oo); } int Prim() { memset(v, 0, sizeof(v)); int ans = 0; for(int i=1; i<=n; i++) { dist[i] = maps[1][i]; pre[i] = 1; } v[1] = 1; for(int i=1; i<n; i++) { int index = -1; int mins = oo; for(int j=1; j<=n; j++) { if(!v[j] && dist[j]<mins) { index = j; mins = dist[j]; } } use[pre[index]][index] = use[index][pre[index]] = 1; ans += mins; v[index] = 1; for(int j=1; j<=n; j++) { if(v[j] && index != j) path[index][j] = path[j][index] = max(path[pre[j]][j], mins); if(!v[j] && dist[j]>maps[index][j]) { dist[j] = maps[index][j]; pre[j] = index; } } } return ans; } int OK()//判断是否有次小生成树 { for(int i=1; i<=n; i++) { for(int j=i+1; j<=n; j++) { //如果有边的长度与最小树上的边相等,就说明不唯一了 if(!use[i][j] && path[i][j] == maps[i][j]) return 0; } } return 1; } int main() { int T; scanf("%d", &T); while(T --) { scanf("%d %d", &n, &m); Init(); int a, b, c; while(m --) { scanf("%d %d %d", &a, &b, &c); maps[a][b] = maps[b][a] = c; } memset(path, 0, sizeof(path)); memset(use, 0, sizeof(use)); int ans = Prim(); if(!OK()) printf("Not Unique! "); else printf("%d ", ans); } return 0; }