【分析】最小生成树的唯一性,思路是先判断每条边是否有重边,有的话eq=1,否则0.然后第一次求出最小生成树,将结果记录下来, 然后依次去掉第一次使用过的且含有重边的边,再求一次最小生成树,若结果与第一次结果一样,则不唯一。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
struct node{
int u, v, dis;
bool eq, use, del;
bool operator <(const node &x)const{
return dis < x.dis;
}
};
#define MAXN (100+5)
#define MAXM (20000+5)
int n, m;
node edges[MAXM];
int f[MAXN];
int find(int x){
return x == f[x]? x: (f[x] = find(f[x]));
}
int kruscal(bool ok){
for(int i = 1; i <= n; i++) f[i] = i;
int ret = 0, tot = 0;
for(int i = 1; i <= m; i++)
if(!edges[i].del){
int u = edges[i].u, v = edges[i].v, dis = edges[i].dis;
int x = find(u), y = find(v);
if(x != y){
tot++; ret += dis;
f[x] = y;
if(ok) edges[i].use = true;
if(tot >= n-1) break;
}
}
return ret;
}
int main(){
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
int T;
scanf("%d", &T);
while(T--){
scanf("%d%d", &n, &m);
for(int i = 1; i <= m; i++){
scanf("%d%d%d", &edges[i].u, &edges[i].v, &edges[i].dis);
edges[i].eq = edges[i].use = false;
}
for(int i = 1; i <= m; i++)
for(int j = 1; j <= m; j++)
if(i != j && edges[i].dis == edges[j].dis) edges[i].eq = true;
sort(edges+1, edges+m+1);
bool tmp = true;
int minest = kruscal(tmp);
tmp = false;
bool found = false;
for(int i = 1; i <= m; i++)
if(edges[i].eq && edges[i].use){
edges[i].del = true;
int now = kruscal(tmp);
if(now == minest){
found = true;
printf("Not Unique!\n");
edges[i].del = false;
break;
}
edges[i].del = false;
}
if(!found) printf("%d\n", minest);
}
return 0;
}