km算法模板(全局变量delta)

#include <bits/stdc++.h>
#define mem(a, b) memset(a, b, sizeof a)
using namespace std;
const int N = 105;
int w[N][N];// 边权
int la[N], lb[N];// 左、右部点的顶标
bool va[N], vb[N];// 访问标记:是否在交错树中
int match[N];
int n, delta;
bool dfs(int x) {
	va[x] = 1;// 访问标记:x在交错树中
	for (int y = 1; y <= n; y++) {
		if (!vb[y]) {
			if (la[x] + lb[y] == w[x][y]) {// 是一个相等子图
				vb[y] = 1;// 访问标记:y在交错树中
				if (match[y] == -1 || dfs(match[y])) {
					match[y] = x;
					return true;
				}
			}
			else delta = min(delta, la[x] + lb[y] - w[x][y]);
		}
	}
	return false;
}
int km() {
	for (int i = 1; i <= n; i++) {
		la[i] = -(1 << 30);// -inf
		lb[i] = 0;
		for (int j = 1; j <= n; j++) {
			la[i] = max(la[i], w[i][j]);
		}
	}
	for (int i = 1; i <= n; i++) {
		while (true) {
			mem(va, false);
			mem(vb, false);
			delta = (1 << 30);// inf
			if (dfs(i))break;
			for (int j = 1; j <= n; j++) {
				if (va[j])la[j] -= delta;
				if (vb[j])lb[j] += delta;
			}
		}
	}
	int res = 0;
	for (int i = 1; i <= n; i++)res += w[match[i]][i];
	return res;
}
void add(int a, int b, int c) {
	w[a][b] = c;
}
int main()
{
	mem(match, -1);
	n = 4;
	add(1, 1, 5);
	add(1, 3, 10);
	add(2, 2, 5);
	add(2, 4, 10);
	add(3, 1, 10);
	add(3, 3, 5);
	add(4, 2, 10);
	add(4, 4, 5);
	cout << km();
	return 0;
}

此种方法可以再优化

发布了143 篇原创文章 · 获赞 11 · 访问量 8191

猜你喜欢

转载自blog.csdn.net/weixin_43701790/article/details/104009910
今日推荐