Acwing372. 棋盘覆盖 (匈牙利算法)

image
二分图最大匹配
最多取多少条边,满足卡片不重叠--所有选出的边没有公共点--二分图放最多的牌--找到最多的边--二分图上最大匹配。
一条直线的两个端点要被分到两个集合,x+y值是奇数的在一个集合,是偶数的在一个集合。然后二分图最大匹配就行了,每次扫奇数点

#include <bits/stdc++.h>
#define x first
#define y second
using namespace std;
const int N = 102;

bool g[N][N]; int n, m;
pair<int, int> match[N][N];
bool st[N][N];
int dx[4] = {0, 0, 1, -1};
int dy[4] = {1, -1, 0, 0};
bool dfs(int x, int y) {
	for ( int i = 0; i < 4; ++ i ) {
		int nx = dx[i] + x, ny = dy[i] + y;
		if (nx && nx <= n && ny && ny <= n && !g[nx][ny] && !st[nx][ny]) {
			st[nx][ny] = 1;
			pair<int, int> t = match[nx][ny];
			if(t.x == -1 || dfs(t.x, t.y)) {
				match[nx][ny] = {x, y}; return true;//只用存第二个集合匹配第一个集合的哪个点 
			}
		}
	}
	return false;
}
int main () {
	cin >> n >> m; 
	while( m -- ) {
		int x, y; cin >> x >>y;
		g[x][y] = true;
	}
	memset(match, -1, sizeof match);
	int ans = 0;
	for ( int i = 1; i <= n; ++ i ) {
		for ( int j = 1; j <= n; ++ j ) {
			if((i + j) % 2 && !g[i][j]) {
				memset(st, 0, sizeof st);
				if(dfs(i, j)) ++ ans;
			}
		} 
	}
	cout << ans << endl;
	return 0;
}
posted @ 2022-04-05 09:48  qingyanng  阅读(43)  评论(0编辑  收藏  举报