您的位置:首页 > 其它

HDU 3691 Nubulsa Expo(全局最小割)

2017-09-05 13:41 429 查看
4000
题目地址

题意:给你一个无向图,并且给你一个源点,让你自己选择一个汇点,输出最小割。

思路:就是全局最小割的模板,因为全局最小割分为两个块,你只要选择不包含源点的集合中的任意一个点就好了,所以就直接输出最小割。不知道全局最小割定义的可以看这篇博客

#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <iomanip>
#define N 310
#define M 300010
#define LL __int64
#define inf 0x3f3f3f3f
#define lson l,mid,ans<<1
#define rson mid+1,r,ans<<1|1
#define getMid (l+r)>>1
#define movel ans<<1
#define mover ans<<1|1
using namespace std;
const LL mod = 1000000007;
int n, m;
int mapp

;
bool vis
;//是否已并入集合
bool in
;//该点是否已经合并到其它点
int len
;//记录每个点的连通度
struct Stoer_wagner {
int s, t;//为什么不用初始化
void init() {
memset(mapp, 0, sizeof(mapp));
}
int solve(){//找最大生成树
memset(vis, false, sizeof(vis));
memset(len, 0, sizeof(len));
int minlen;//找到的s-t割
int to;
for (int i = 1; i <= n; i++) {
int mmax = -inf;
for (int j = 1; j <= n; j++) {
if (!in[j] && !vis[j] && mmax < len[j]) {//找最大的len值
to = j;
mmax = len[j];
}
}
if (to == t) {//找不到点 图本身不连通
break;
}
vis[to] = true;//标记 已经并入集合
minlen = mmax;
s = t;
t = to;// 记录前、后点
for (int j = 1; j <= n; j++) {//继续找不在集合 且 没有被合并过的点
if (in[j] || vis[j]) {
continue;
}
len[j] += mapp[to][j];//累加 连通度
}
}
return  minlen;
}
int stoer_wagner() {
memset(in, false, sizeof(in));
int ans = inf;
for (int i = 1; i < n; i++) {
ans = min(ans, solve());
if (ans == 0) return 0;//本身不连通
in[t] = true;
for (int j = 1; j <= n; j++) {//把t点合并到s点
if (in[j]) continue;//已经合并
mapp[s][j] += mapp[t][j];
mapp[j][s] += mapp[j][t];
}
}
return ans;
}
}sw;
int main() {
cin.sync_with_stdio(false);
int a, b, c;
while (cin >> n >> m >> c) {
if (n == 0 && m == 0 && c == 0) break;
sw.init();
for (int i = 0; i < m; i++) {
cin >> a >> b >> c;
mapp[a][b] += c;
mapp[b][a] += c;
}
cout << sw.stoer_wagner() << endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: