study and life share of wss

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 110;
int Map[maxn][maxn];
bool vis[maxn];
int pre[maxn];
int dis[maxn];
int MaxPath[maxn][maxn];
//MaxPath[i][j] 指的是在i -> j 在最小生成树的路径上的最大的边
bool used[maxn][maxn];
//判断在最小生成树中是不是有这么一条边
int T, m, n;

void init()
{
memset(dis, 0x3f, sizeof(dis));
memset(Map, 0x3f, sizeof(Map));
memset(vis, 0, sizeof(vis));
memset(used, 0, sizeof(used));
memset(pre, 0, sizeof(pre));
}

int primMST()
{
for(int i = 1; i <= n; i++){
dis[i] = Map[i][1];
pre[i] = 1; //初始化,让每一个点的父亲节点都变成1
}
dis[1] = 0; vis[1] = true;
int ans = 0;

for(int i = 1; i < n; i++){
int temp = INF, pos;
for(int j = 1; j <= n; j++){
if(!vis[j] && temp > dis[j]){
temp = dis[j], pos = j;
}
}

if(temp == INF) return -1;
used[pre[pos]][pos] = used[pos][pre[pos]] = 1;
ans += dis[pos];
vis[pos] = true;

for(int j = 1; j <= n; j++){
if(vis[j] && j != pos) MaxPath[j][pos] = MaxPath[pos][j] = max(MaxPath[j][pre[pos]], dis[pos]);
if(!vis[j] && dis[j] > Map[pos][j]) {dis[j] = Map[pos][j], pre[j] = pos;}
}
}
return ans;
}

int FindSMST(int x)
//遍历每一条边,让最小生成树加上这一条边,这样就构成了一个回路,然后减掉这两个点之间最大的那一条边
{
int ans = INF;
for(int i = 1; i <= n; i++){
for(int j = 1; j <= n; j++){
if(i != j && !used[i][j])
ans = min(ans, x+Map[i][j]-MaxPath[i][j]);
}
}
return ans;
}

int main()
{
scanf("%d", &T);
while(T--){
init();
scanf("%d %d", &n, &m);
while(m--){
int v1, v2, w;
scanf("%d %d %d", &v1, &v2, &w);
Map[v1][v2] = Map[v2][v1] = w;
}
int ans1 = primMST();
int ans2 = FindSMST(ans1);
if(ans1 != ans2) cout << ans1 << endl;
else cout << "Not Unique!" << endl;
}
return 0;
}