[圖論]POJ – 1679 – The Unique MST(次小生成樹)
阿新 • • 發佈:2021-01-06
技術標籤:圖論
我寫了個暴力的演算法,先求一遍最小生成樹。然後列舉所有最小生成樹的邊依次刪除,每次再計算一次最小生成樹,取最小值,然後和一開始求的值比較。原理是次小生成樹的邊一定至少有一條和最小生成樹的不一樣。
注意:刪除一條邊之後圖可能不連通,不連通的圖沒有生成樹,應該返回最大值。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define maxn 10005
struct edge{
int u, v, c, p;
}g[maxn];
int par[maxn], n, m;
int find(int x){return par[x] < 0 ? x : par[x] = find(par[x]);}
bool comp(const edge &a, const edge &b){return a.c < b.c;}
int mst()
{
memset(par, -1, sizeof(par));
int ans = 0;
for (int i = 0; i < m; ++i){
if (g[i].p == 2) continue;
int x = find(g[i].u), y = find(g[i].v);
if (x != y){
ans += g[i].c;
par[x] += par[y];
par[y] = x;
}
}
if (-par[find(g[0].u)] != n) return 0x3f3f3f3f;
else return ans;
}
int main()
{
int t;
scanf("%d", &t);
while (t--){
scanf("%d %d" , &n, &m);
for (int i = 0; i < m; ++i) scanf("%d %d %d", &g[i].u, &g[i].v, &g[i].c);
std::sort(g, g + m, comp);
int ans = 0;
memset(par, -1, sizeof(par));
for (int i = 0; i < m; ++i){
int x = find(g[i].u), y = find(g[i].v);
if (x != y){
g[i].p = 1;
ans += g[i].c;
par[x] += par[y];
par[y] = x;
}
}
if (-par[find(g[0].u)] != n) puts("Not Unique!");
else{
int tans = 0x3f3f3f3f;
for (int i = 0; i < m; ++i){
if (g[i].p == 1){
g[i].p = 2;
tans = std::min(tans, mst());
g[i].p = 0;
}
}
if (ans == tans) puts("Not Unique!");
else printf("%d\n", ans);
}
}
return 0;
}