题目大意是,给定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)
{
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;
}