Description
Input
Output
Sample Input
2 3 3 1 2 1 2 3 2 3 1 3 4 4 1 2 2 2 3 2 3 4 2 4 1 2
Sample Output
3 Not Unique!
判断最小生成树是不是唯一的,那么只需要判断最小生成树与次小生成树是否相等,若相等则不是唯一的,若不等则是唯一的:
#include<stdio.h> #include<string.h> #define INF 0x3f3f3f3f #define N 110 #define max(a, b) (a > b ? a : b) #define min(a, b) (a < b ? a : b) int G[N][N], M[N][N], dist[N], f[N], n; int visit[N], mark[N][N]; //标记数组 void Init() { int i, j; memset(visit, 0, sizeof(visit)); memset(mark, 0, sizeof(mark)); memset(M, 0, sizeof(M)); for (i = 0; i <= n; i++) { for (j = 0; j <= n; j++) { if (i == j) G[i][j] = 0; else G[i][j] = INF; } } } int Prim() { int i, j, Min, idex, ans = 0; visit[1] = 1; for (i = 1; i <= n; i++) { dist[i] = G[1][i]; f[i] = 1; } for (i = 1; i < n; i++) { Min = INF; for (j = 1; j <= n; j++) { if (!visit[j] && dist[j] < Min) { Min = dist[j]; idex = j; } } ans += Min; visit[idex] = 1; //将已经在最小生成树的结点标记下来 mark[f[idex]][idex] = mark[idex][f[idex]] = 1; //将已经在最小生成树里的边标记下来 for (j = 1; j <= n; j++) { if (visit[j] && j != idex) M[j][idex] = M[idex][j] = max(M[f[idex]][j], G[f[idex]][idex]); //记录两个最小生成树结点之间最大的一条边 //M[j][idex] = M[idex][j] = max(M[f[idex]][j], dist[idex]); if (!visit[j] && dist[j] > G[idex][j]) { dist[j] = G[idex][j]; f[j] = idex; //更新上一个结点 } } } return ans; } int Second(int ans) { int i, j, Min = INF; for (i = 1; i <= n; i++) { for (j = i+1; j <= n; j++) { if (!mark[i][j] && G[i][j] != INF) Min = min(Min, ans+G[i][j]-M[i][j]); //每次遍历时加上一个不是最小生成树中的边,需要将形成回路的最小生成树最大边减去才能形成次小生成树 } } return Min; } int main () { int T, m, a, b, c, ans1, ans2; scanf("%d", &T); while (T--) { scanf("%d %d", &n, &m); Init(); while (m--) { scanf("%d %d %d", &a, &b, &c); G[a][b] = c; G[b][a] = c; } ans1 = Prim(); //计算最小生成树的权值 ans2 = Second(ans1); //计算次小生成树的权值 if (ans1 == ans2) printf("Not Unique!\n"); else printf("%d\n", ans1); } return 0; }