题目链接:http://poj.org/problem?id=1679
问给出的图中的最小生成树是否唯一。
我们求次小生成树,如果两个生成树的权值和相等,说明最小生成树不唯一。
这里我使用了kruskal,遍历最小生成树中的边,删除后重新求最小生成树,来确定次小生成树。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int INF = 1e9+10;
struct Edge{
int from, to, len;
}e[10005];
int used[205], n, m;
int cnt, father[205];
int fnd(int x){
if (father[x] != x) father[x] = fnd(father[x]);
return father[x];
}
bool uni(int x, int y){
int fx = fnd(x), fy = fnd(y);
if (fx == fy) return false;
father[fx] = fy;
return true;
}
bool cmp(Edge a, Edge b){
return a.len < b.len;
}
void init(){
for (int i = 1; i <= n; i++)
father[i] = i;
}
int kruskal(int use){
int ans = 0, num = 0;
for (int i = 1; i <= m; i++){
if (i == use) continue;
int from = e[i].from, to = e[i].to, len = e[i].len;
if (uni(from, to)){
ans += len; num++;
if (use == 0) used[++cnt] = i;
}
}
if (num < n-1) return -1;
return ans;
}
int main(){
std::ios::sync_with_stdio(false);
int T;
cin >> T;
while(T--){
cin >> n >> m; cnt = 0;
for (int i = 1; i <= m; i++){
int from, to, len;
cin >> from >> to >> len;
e[i] = Edge{from, to, len};
}
init();
sort(e+1, e+m+1, cmp);
int ans = kruskal(0);
int ans2 = INF;
for (int i = 1; i <= cnt; i++) init(), ans2 = min(ans2, kruskal(used[i]));
if (ans2 == ans) cout << "Not Unique!" << endl;
else cout << ans << endl;
}
return 0;
}