无源汇点的最小割问题 Stoer–Wagner
也称为全局最小割。定义补充(与《网络流》中的定义不同):
割:是一个边集,去掉其中所有边能使一张网络流图不再连通(即分成两个子图)。
通过递归的方式来解决无向正权图上的全局最小割问题,算法复杂度 \(\mathcal O(VE + V^{2}\log V)\) ,一般可近似看作 \(\mathcal O(V^3)\) 。
signed main() {int n, m;cin >> n >> m;DSU dsu(n); // 这里引入DSU判断图是否联通,如题目有保证,则不需要此步骤vector<vector<int>> edge(n + 1, vector<int>(n + 1));for (int i = 1; i <= m; i++) {int x, y, w;cin >> x >> y >> w;dsu.merge(x, y);edge[x][y] += w;edge[y][x] += w;}if (dsu.Poi(1) != n || m < n - 1) { // 图不联通cout << 0 << endl;return 0;}int MinCut = INF, S = 1, T = 1; // 虚拟源汇点vector<int> bin(n + 1);auto contract = [&]() -> int { // 求解S到T的最小割,定义为 cut of phasevector<int> dis(n + 1), vis(n + 1);int Min = 0;for (int i = 1; i <= n; i++) {int k = -1, maxc = -1;for (int j = 1; j <= n; j++) {if (!bin[j] && !vis[j] && dis[j] > maxc) {k = j;maxc = dis[j];}}if (k == -1) return Min;S = T, T = k, Min = maxc;vis[k] = 1;for (int j = 1; j <= n; j++) {if (!bin[j] && !vis[j]) {dis[j] += edge[k][j];}}}return Min;};for (int i = 1; i < n; i++) { // 这里取不到等号int val = contract();bin[T] = 1;MinCut = min(MinCut, val);if (!MinCut) {cout << 0 << endl;return 0;}for (int j = 1; j <= n; j++) {if (!bin[j]) {edge[S][j] += edge[j][T];edge[j][S] += edge[j][T];}}}cout << MinCut << endl;
}