【题意】:问图中的最小生成树是否唯一。
【题解】:先求出最小生成树,再求次小生成树,如果最小生成树 == 次小生成树,则不唯一;否则,唯一。纯粹模板题。
【代码】:
1 #include "iostream"
2 #include "cstdio"
3 #include "cstring"
4 #include "algorithm"
5 #include "vector"
6 #include "queue"
7 #include "cmath"
8 #include "string"
9 #include "cctype"
10 using namespace std;
11 #define pb push_back
12 #define lc(x) (x << 1)
13 #define rc(x) (x << 1 | 1)
14 #define lowbit(x) (x & (-x))
15 #define ll long long
16 const int inf = 1 << 30;
17 #define maxn 150
18 int maz[maxn][maxn], path[maxn][maxn];
19 bool visit[maxn];
20 int dist[maxn], pre[maxn], stack[maxn];
21 int n, m;
22
23 void init() {
24 for (int i = 1; i <= n; i++)
25 for (int j = 1; j <= n; j++)
26 maz[i][j] = inf, path[i][j] = 0;
27 }
28
29 int Prim(int s) {
30 for (int i = 1; i <= n; i++) dist[i] = maz[s][i], visit[i] = 0, pre[i] = s;
31 int top = 0, sum = 0;
32 visit[s] = true, dist[s] = 0, stack[top++] = s;
33 while (1) {
34 int u = -1;
35 for (int i = 1; i <= n; i++)
36 if (!visit[i] && (u == -1 || dist[u] > dist[i]))
37 u = i;
38 if (u == -1) break;
39 sum += dist[u], stack[top++] = u, visit[u] = true;
40 for (int i = 0; i < top; i++) {
41 if (stack[i] == u) continue;
42 path[stack[i]][u] = max(path[pre[u]][stack[i]], dist[u]);
43 path[u][stack[i]] = path[stack[i]][u];
44 }
45 for (int i = 1; i <= n; i++)
46 if (!visit[i] && (maz[u][i] < dist[i]))
47 dist[i] = maz[u][i], pre[i] = u;
48 }
49 return sum;
50 }
51
52 void SMT() {//次小生成树
53 int Min = inf, sum = Prim(1);//先求一次最小生成树
54 for (int i = 1; i < n; i++)
55 for (int j = i + 1; j <= n; j++)
56 if (pre[i] != j && pre[j] != i && maz[i][j] < inf)
57 Min = min(Min, sum - path[i][j] + maz[i][j]);
58 if (Min == sum) puts("Not Unique!");
59 else printf("%d\n", sum);
60 }
61
62 int main() {
63 int T, u, v, w;
64 scanf("%d", &T);
65 while(T--) {
66 scanf("%d%d", &n, &m);
67 init();
68 for(int i = 0; i < m; i++) {
69 scanf("%d%d%d", &u, &v, &w);
70 maz[u][v] = maz[v][u] = w;
71 }
72 SMT();
73 }
74 return 0;
75 }