Knight placed ch6091 (bipartite graph maximum independent set)

Topic Link  https://www.acwing.com/problem/content/380/

Ideas:

Let each other seeking the maximum number of knights can not attack put. It can be considered, the drawing point may be linked to each other edge of attack, it will be a graph, and is a bipartite graph. If you can not tell what is left portion of the node which is the right part of the node, you can use staining them separately. Now no connection is required between a maximum set to meet any set of points, i.e. the maximum independent set. = Total maximum independent set bipartite graph point - maximum matching. In this problem, the total number of points of the bipartite graph can be represented by the dyeing method points stained, simpler representation is, a total of n * m points, which in turn t points are banned placed, then this t points it will not appear in the bipartite graph, so the total number of points is the n-MT * , then the biggest construction diagram seeking to match.

/**
 * Author: correct
 */
#include <bits/stdc++.h>
using namespace std;
#define mem(a, b) memset(a, b, sizeof a)
const int N = 1e5;
int head[N], nex[N], to[N], cnt;
int n, m, t;
int color[110][110];
int dx[] = {2, 2, -2, -2, 1, 1, -1, -1};
int dy[] = {1, -1, 1, -1, 2, -2, 2, -2};
int match[N];
bool w[110][110];
bool vis[N];
void pre_work(){
	mem(head, -1);
	mem(nex, -1);
	cnt = 0;
	mem(color, 0);
	mem(match, -1);
	mem(w, true);
}
void add(int a, int b){
	++cnt;
	to[cnt] = b;
	nex[cnt] = head[a];
	head[a] = cnt;
}
int get(int x, int y){
	return (x - 1) * 1000 + y;
}
bool check(int xx, int yy){
	if (xx >= 1 && xx <= n && yy >= 1 && yy <= m && w[xx][yy])return 1;
	return 0;
}
void build(){
	for (int i = 1; i <= n; i++){
		for (int j = 1; j <= m; j++){
			for (int k = 0; k <= 7; k++){
				int xx = i + dx[k];
				int yy = j + dy[k];
				if (check(xx, yy)){
					add(get(i, j), get(xx, yy));
				}
			}
		}
	}
}
int getX(int x){
	return x / 1000 + 1;
}
int getY(int x){
	return x % 1000;
}
bool colors(int x, int c){
	int xx, yy;
	yy = x % 1000;
	xx = x / 1000 + 1;
	color[xx][yy] = c;
	for (int i = head[x]; ~i; i = nex[i]){
		int y = to[i];
		if (!color[getX(y)][getY(y)]){
			colors(y, 3 - c);
		}
		else if(color[getX(y)][getY(y)] == c){
			return 0;
		}
	}
	return 1;
}
bool dfs(int x){
	for (int i = head[x]; ~i; i = nex[i]){
		int y = to[i];
		if (vis[y])continue;
		vis[y] = 1;
		if (match[y] == -1 || dfs(match[y])){
			match[y] = x;
			return 1;
		}
	}
	return 0;
}
int solve(){
	build();
	int ans = n * m - t;
	for (int i = 1; i <= n; i++){
		for (int j = 1; j <= m; j++){
			if (!color[i][j])colors(get(i, j), 1);
		}
	}
	for (int i = 1; i <= n; i++){
		for (int j = 1; j <= m; j++){
			if (color[i][j] == 1 && w[i][j]){
				mem(vis, 0);
				if (dfs(get(i, j)))ans--;
			}
		}
	}
	return ans;
}
int main()
{
	pre_work();
	scanf("%d %d %d", &n, &m, &t);
	for (int i = 0; i < t; i++){
		int x, y;
		scanf("%d %d", &x, &y);
		w[x][y] = 0;
	}
	printf("%d\n", solve());
	return 0;
}

 

Published 204 original articles · won praise 13 · views 10000 +

Guess you like

Origin blog.csdn.net/weixin_43701790/article/details/104662347