题目大意是,给定N个顶点,M条边,两个顶点之间可能有多条边,求至少删除多少条边才能将该图分成两个子图。
最小割集,典型的算法Stoer-Wagner,就是那篇论文,这里也就不复制过来了,只是用Prim求最大生成树时,更新的“边”不是普通意义上的边,而是顶点到所有已划分集合中的所有点的边权值和,这里要特别注意~ 直接贴代码~
#include <stdio.h> #include <vector> #include <math.h> #include <string.h> #include <string> #include <iostream> #include <queue> #include <list> #include <algorithm> #include <stack> #include <map> #include <time.h> using namespace std; int G[501][501]; bool Visited[501]; int D[501]; int Edge[501]; int main() { #ifdef _DEBUG freopen("e:\\in.txt", "r", stdin); #endif int n, m; while (scanf("%d %d", &n, &m) != EOF) { //memset(OriG, 0, sizeof(OriG)); for (int i = 0; i < m; i++) { int s, t, v; scanf("%d %d %d", &s, &t, &v); G[s][t] += v; G[t][s] += v; } int minans = 1000000000; int s = 0; int v = -1; Edge[0] = 0; for (int c = 0; c < n - 1;c++) { memset(Visited, 0, sizeof(Visited)); memset(D, 0, sizeof(D)); // s = Edge[s]; s = 0; Visited[s] = true; D[s] = 0; while (true) { int minedge = 0; v = -1; for (int i = 0; i < n; i++) { if (!Visited[i] /*&& G[s][i] > D[i]*/) { D[i] += G[s][i]; } if (!Visited[i] && D[i] > minedge) { minedge = D[i]; v = i; } } if (v == -1) { break; } Edge[v] = s; s = v; Visited[s] = true; } int total = 0; for (int i = 0; i < n; i++) { total += G[s][i]; } if (total < minans) { minans = total; } G[s][Edge[s]] = 0; G[Edge[s]][s] = 0; for (int i = 0; i < n; i++) { G[Edge[s]][i] += G[s][i]; G[i][Edge[s]] += G[i][s]; G[i][s] = 0; G[s][i] = 0; } } printf("%d\n", minans); } return 0; }
POJ2914 Minimum Cut 最小割集,布布扣,bubuko.com
原文地址:http://blog.csdn.net/u011363774/article/details/38541963