1. 程式人生 > 其它 >[圖論]POJ – 1679 – The Unique MST(次小生成樹)

[圖論]POJ – 1679 – The Unique MST(次小生成樹)

技術標籤:圖論

我寫了個暴力的演算法,先求一遍最小生成樹。然後列舉所有最小生成樹的邊依次刪除,每次再計算一次最小生成樹,取最小值,然後和一開始求的值比較。原理是次小生成樹的邊一定至少有一條和最小生成樹的不一樣。
注意:刪除一條邊之後圖可能不連通,不連通的圖沒有生成樹,應該返回最大值。

#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; }