2020-08-16 省選集訓選講
阿新 • • 發佈:2020-08-16
Problem T3. 高中題
考慮這樣一個不等式
\[w_a+\delta _a\leq w_b+\delta _b \]
移項可得
\[w_a-w_b\leq \delta_a+\delta_b \]
左邊為邊權,右邊為頂標和。
用 KM 計算出頂標。
#include <bits/stdc++.h> using namespace std; const int N = 400; int g[N][N]; int main() { int n, m; cin >> n >> m; vector<int> weight(m); vector<vector<pair<int, int>>> graph(n); for (int i = 0; i < n - 1; ++i) { int u, v, w; cin >> u >> v >> w; --u, --v; weight[i] = w; graph[u].emplace_back(v, i); graph[v].emplace_back(u, i); } for (int i = n - 1; i < m; ++i) { int u, v, w; cin >> u >> v >> w; --u, --v; weight[i] = w; vector<int> vis(n, 0); function<bool(int u, int goal)> dfs = [&](int u, int goal) { vis[u] = 1; if (u == goal) { return true; } for (auto e : graph[u]) { int v = e.first, id = e.second; if (vis[v]) { continue; } if (dfs(v, goal)) { if (weight[id] > w) { g[id][i - n + 1] = weight[id] - w; } return true; } } return false; }; dfs(u, v); } auto km = [&]() { int N = max(n - 1, m - n + 1); vector<bool> visx(N); vector<bool> visy(N); vector<int> match(N); vector<int> slack(N); vector<int> valx(N); vector<int> valy(N); fill(match.begin(), match.end(), -1); for (int i = 0; i < N; ++i) { valx[i] = valy[i] = 0; for (int j = 0; j < N; ++j) { valx[i] = max(valx[i], g[i][j]); } } for (int i = 0; i < N; ++i) { fill(slack.begin(), slack.end(), 0x3f3f3f3f); while (true) { fill(visx.begin(), visx.end(), 0); fill(visy.begin(), visy.end(), 0); function<bool(int u)> dfs = [&](int u) { visx[u] = 1; for (int v = 0; v < N; ++v) { int w = g[u][v]; if (visy[v]) { continue; } if (valx[u] + valy[v] - w == 0) { visy[v] = true; if (match[v] == -1 || dfs(match[v])) { match[v] = u; return true; } } else { slack[v] = min(slack[v], valx[u] + valy[v] - w); } } return false; }; if (dfs(i)) { break; } int d = 0x3f3f3f3f; for (int j = 0; j < N; ++j) { if (!visy[j]) { d = min(d, slack[j]); } } for (int j = 0; j < N; ++j) { if (visx[j]) { valx[j] -= d; } if (visy[j]) { valy[j] += d; } else { slack[j] -= d; } } } } int ans = 0; for (int i = 0; i < m; ++i) { ans += (i < n - 1 ? valx[i] : valy[i - n + 1]); } cout << ans << '\n'; }; km(); return 0; }