hdu2255 KM(带权二分图匹配)

这道题就是一个裸的带权二分图(KM)匹配模板。
首先关于KM算法,我概念是看的这个视频(在2P)
https://www.bilibili.com/video/av60813417/?p=2&t=316
然后关于代码方面我是看的这个博客
https://blog.csdn.net/frankax/article/details/81541421
都是感觉非常不错。
然后直接写模板就可以了。

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
const int INF = 1e9+7;
const int max_ = 3e2 + 7;
int match[max_], n, map[max_][max_];
int lx[max_], ly[max_],slack[max_],visx[max_],visy[max_];
inline int read()
{
	int s = 0, f = 1;
	char ch = getchar();
	while (ch<'0' || ch>'9') {
		if (ch == '-')
			f = -1;
		ch = getchar();
	}
	while (ch >= '0'&&ch <= '9') {
		s = s * 10 + ch - '0';
		ch = getchar();
	}
	return s * f;
}

inline int max(int x, int y) {
	return x > y ? x : y;
}
inline int min(int x, int y) {
	return x > y ? y : x;
}
int dfs(int now) {
	visx[now] = 1;
	for (register int i = 1; i <= n; i++) {
		if (!visy[i] && lx[now] + ly[i] == map[now][i]) {
			visy[i] = 1;
			if (!match[i] || dfs(match[i])) {			
				match[i] = now;
				return 1;
			}
		}
		else{
			slack[i] = min(slack[i], lx[now] + ly[i] - map[now][i]);
		}
	}
	return 0;
}

void KM() {
	memset(ly, 0, sizeof(ly));
	memset(match, 0, sizeof(match));
	for (register int i = 1; i <= n; i++) {
		lx[i] = -INF;
		for (register int j = 1; j <= n; j++) {
			lx[i] = max(lx[i], map[i][j]);
		}
	}
	for (register int x = 1; x <= n; x++) {
		memset(slack, INF, sizeof(slack));
		while (1) {
			memset(visx, 0, sizeof(visx));
			memset(visy, 0, sizeof(visy));
			if (dfs(x))break;
			int D = INF;
			for (register int i = 1; i <= n; i++) {
				if (!visy[i]) D = min(D, slack[i]);
			}
			for (register int i = 1; i <= n; i++) {
				if (visx[i]) lx[i] -= D;
                if (visy[i]) ly[i] += D;
				else
				{
					slack[i] -= D;
				}
			}
			
		}
	}
}

int main() {
	while (~scanf("%d", &n)) {
		memset(map, 0, sizeof(map));
		for (register int i = 1; i <= n; i++) {
			for (register int j = 1; j <= n; j++) {
				map[i][j] = read();
			}
		}
		KM();
		int ans = 0;
		for (register int i = 1; i <= n; i++) {
			ans += map[match[i]][i];
		}
		printf("%d\n", ans);
	}
	return 0;
}
发布了32 篇原创文章 · 获赞 3 · 访问量 671

猜你喜欢

转载自blog.csdn.net/qq_43804974/article/details/101110920