传送门:QAQ
题意:就是让你求出图中的最小割
思路:模板题,使用Store-Wagner 算法能快速求出最小割
附上代码:
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <math.h>
#include <bitset>
#include <algorithm>
#include <climits>
using namespace std;
const int inf=0x3f3f3f3f;
typedef long long LL;
const int maxn = 5100;
int ax[maxn];
int bn[maxn];
int gx[510][510];
int dis[510];
int v[510];
int vis[510];
int Stoer_Wagner(int n)
{
int i, j, res = inf;
for (i = 0; i < n; i++)
v[i] = i;////保存顶点 ,固定顶点为自己
while (n > 1)
{
//pre用来表示之前加入A集合的点
//我们每次都以0点为第一个加入A集合的点
int k = 1, pre = 0;
for (i = 1; i < n; i++) {
dis[v[i]] = gx[v[0]][v[i]];
if (dis[v[i]] > dis[v[k]])
k = i;
}
memset(vis, 0, sizeof(vis));
vis[v[0]] = true;//标记该点已经加入A集合
for (i = 1; i < n; i++)
{
if (i == n - 1)//最后一次加入的点就要更新答案
{
res = min(res, dis[v[k]]);
for (j = 0; j < n; j++) //将该点合并到pre上,相应的边权就要合并
{
gx[v[pre]][v[j]] += gx[v[j]][v[k]];
gx[v[j]][v[pre]] += gx[v[j]][v[k]];
}
v[k] = v[--n];//删除最后一个点
}
vis[v[k]] = true;
pre = k;
k = -1;
for (j = 1; j < n; j++)
if (!vis[v[j]])
{
//将上次求的 k 加入集合,合并与它相邻的边到割集
dis[v[j]] += gx[v[pre]][v[j]];
if (k == -1 || dis[v[k]] < dis[v[j]])
k = j;
}
}
}
return res;
}
int main(void) {
int n, m;
while (scanf("%d%d", &n, &m) != EOF) {
memset(gx, 0, sizeof(gx));
for (int i = 0; i < m; i++) {
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
gx[a][b] += c;
gx[b][a] += c;
}
printf("%d\n", Stoer_Wagner(n));
}
return 0;
}