POJ1679 The Unique MST
阿新 • • 發佈:2020-08-14
題目大意是給你一個無向圖,讓你判斷該圖的最小生成樹(MST)是否唯一。
要判斷最小生成樹是否唯一,只需判斷次小生成樹和最小生成樹的大小關係即可。要求次小生成樹,就得先求最小生成樹,在最小生成樹的基礎上進行列舉非MST邊,每加一條非MST邊,就會形成一個環,然後求這個環內的最大邊權,依次列舉求最小值即可,這個環就是從非MST邊的端點到兩端點的LCA,所以要求一下LCA,順便維護一下樹上ST表,進行快速的查詢最大值。
#pragma GCC optimize(2) #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <cmath> #include <map> using namespace std; typedef long long ll; #define sc(z) scanf("%d", &(z)) #define _ff(i, a, b) for (int i = (a); i <= (b); ++i) #define _f(i, a, b) for (int i = (a); i < (b); ++i) #define _rr(i, a, b) for (int i = (a); i >= (b); --i) #define _r(i, a, b) for (int i = (a); i > (b); --i) const int inf = 0x3f3f3f3f; const int maxn = 105; int mp[maxn][maxn]; vector<int> G[maxn]; struct node{ int from, to, id, w; }e[maxn * maxn]; vector<node> C; int dep[maxn], anc[maxn][25], v[maxn * maxn]; int mx[maxn][25]; int n, m, tot, fa[maxn], f[maxn]; void dfs(int u, int v) { _ff(i, 1, 20) { anc[u][i] = anc[anc[u][i - 1]][i - 1]; mx[u][i] = max(mx[u][i - 1], mx[anc[u][i - 1]][i - 1]); } _f(i, 0, G[u].size()) { int k = G[u][i]; if (k == v) continue; anc[k][0] = u; dep[k] = dep[u] + 1; mx[k][0] = mp[k][u]; dfs(k, u); } } int lca(int u, int v) { if (dep[u] < dep[v]) swap(u, v); _rr(i, 20, 0) { if (dep[anc[u][i]] >= dep[v]) u = anc[u][i]; } if (u == v) return v; _rr(i, 20, 0) { if (anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i]; } return anc[u][0]; } bool cmp(node a, node b) { return a.w < b.w; } int find_fa(int x) { while (x != fa[x]) x = fa[x] = fa[fa[x]]; return x; } int qmax(int u, int v) { if (u == v) return 0; int k = log(dep[u] - dep[v] + 1); return mx[u][k]; } void solve() { sort(e + 1, e + 1 + tot, cmp); _ff(i, 1, n) fa[i] = i; int cnt = 0, minn = 0, ans = inf; _ff(i, 1, n) fa[i] = i; _ff(i, 1, tot) { int x = find_fa(e[i].from), y = find_fa(e[i].to); if (x == y) { C.push_back(e[i]); continue; } fa[x] = y; G[e[i].from].push_back(e[i].to); G[e[i].to].push_back(e[i].from); minn += e[i].w; v[e[i].id>>1] = 1; if (++cnt == n - 1) break; } _ff(i, cnt + 1, tot) C.push_back(e[i]); dep[1] = 0, dep[0] = -1; dfs(1, 0); _f(i, 0, C.size()) { if (v[C[i].id>>1]) continue; int fr = C[i].from, to = C[i].to; int ca = lca(fr, to); int tmp = max(qmax(fr, ca), qmax(to, ca)); ans = min(ans, minn - tmp + C[i].w); v[C[i].id>>1] = 1; } if (ans == minn) cout << "Not Unique!" << endl; else printf("%d\n", minn); } signed main() { int kase; scanf("%d", &kase); while (kase--) { tot = 0; int x, y, z; scanf("%d%d", &n, &m); _ff(i, 1, m) { scanf("%d%d%d", &x, &y, &z); ++tot; e[tot] = {x, y, tot + 1, z}; ++tot; e[tot] = {y, x, tot + 1, z}; mp[x][y] = mp[y][x] = z; } solve(); C.clear(); _ff(i, 1, n) G[i].clear(); memset(v, 0, sizeof(v)); memset(mx, 0, sizeof(mx)); } return 0; }