全局最小割stoer wagner c++模板

#include <iostream>

using namespace std;
#define MAXN 110
int graph[MAXN][MAXN];
int v[MAXN]; //i为结点初始编号, v[i]为结点当前编号, 便于删除结点并使序号始终连续
int wage[MAXN]; //该点加入之前集合中的所有顶点到该点的边权之和
bool mark[MAXN]; //标记顶点是否加入集合

int stoer_wagner(int n) {
	int mincut = -1;
	for (int i = 0; i < n; i++)
		v[i] = i; //初始结点编号为自己
	while (n > 1) { //(最初n) - 1轮
		for (int i = 0; i < n; i++) {
			wage[v[i]] = 0;
			mark[v[i]] = false;
		}
		int pre = 0; //前一个加入集合的结点, 每次都从0开始
		mark[v[pre]] = true; //结点0加入集合
		for (int i = 1; i < n; i++) { //(当前n) - 1轮
			int maxWageP = -1;
			for (int j = 1; j < n; j++) { //根据前一个加入集合的结点更新wage, 并找到最大wage的点
				if (mark[v[j]]) //j只用来遍历所有结点, 实际使用结点都需套上v, v[j]才是与graph对应的结点编号 
					continue;
				wage[v[j]] += graph[v[pre]][v[j]]; //若没有边则加0, 不影响
				if (maxWageP == -1 || wage[v[maxWageP]] < wage[v[j]]) 
					maxWageP = j;
			}
			mark[v[maxWageP]] = true; //wage最大的结点加入集合
			if (i == n - 1) { //最后一个加入集合的结点, 即T结点, 更新最小割
				if (mincut == -1 || wage[v[maxWageP]] < mincut)
					mincut = wage[v[maxWageP]];
				//将T点contract到S结点上,然后删除T, T即v[maxWageP], S即pre
				for (int j = 0; j < n; j++) {
					graph[v[pre]][v[j]] += graph[v[maxWageP]][v[j]];
					graph[v[j]][v[pre]] += graph[v[j]][v[maxWageP]];
				}
				n--; //删除点T后结点个数应减1
				v[maxWageP] = v[n]; //下一轮结点应存储在v0到(n - 1), 最后一个结点与T交换编号达到删除T的目的 
			}
                        pre = maxWageP;
		}
	}
	return mincut;
}

int main() {
	int n, m;
	while (cin >> n >> m) {
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				graph[i][j] = 0; //0代表没有边
			}
		}
		while (m--) {
			int x, y, c;
			cin >> x >> y >> c;
			graph[x][y] += c; //同一对顶点可能有多条边
			graph[y][x] += c;
		}
		cout << stoer_wagner(n) << endl;
	}
}

参考

https://blog.csdn.net/discreeter/article/details/52556366

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值