BZOJ_3175_[Tjoi2013]攻击装置_二分图匹配

BZOJ_3175_[Tjoi2013]攻击装置_二分图匹配

Description

给定一个01矩阵,其中你可以在0的位置放置攻击装置。每一个攻击装置(x,y)都可以按照“日”字攻击其周围的 8个位置(x-1,y-2),(x-2,y-1),(x+1,y-2),(x+2,y-1),(x-1,y+2),(x-2,y+1), (x+1,y+2),(x+2,y+1)
求在装置互不攻击的情况下,最多可以放置多少个装置。

Input

第一行一个整数N,表示矩阵大小为N*N。接下来N行每一行一个长度N的01串,表示矩阵。

Output

一个整数,表示在装置互不攻击的情况下最多可以放置多少个装置。

Sample Input

3
010
000
100

Sample Output

4

黑白染色,对两个能攻击到的0的位置连边。
求二分最大独立集。
最大独立集=总可用点数-二分图最大匹配。
 
代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 40050
#define M 300050
int head[N],to[M],nxt[M],cnt,n,vis[N],match[N],tot,a[220][220],idx[220][220],la;
int tx[]={-1,-2,-2,-1};
int ty[]={-2,-1,1,2};
inline void add(int u,int v) {
	to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
bool dfs(int x) {
	int i;
	for(i=head[x];i;i=nxt[i]) {
		if(vis[to[i]]!=tot) {
			vis[to[i]]=tot;
			if(!match[to[i]]||dfs(match[to[i]])) {
				match[to[i]]=x; return 1;
			}
		}
	}
	return 0;
}
int main() {
	scanf("%d",&n);
	int i,j,k,sum=0;
	for(i=1;i<=n;i++) {
		for(j=1;j<=n;j++) {
			scanf("%1d",&a[i][j]);
			idx[i][j]=++la;
			if(a[i][j]) continue;
			sum++;
			for(k=0;k<4;k++) {
				int di=i+tx[k],dj=j+ty[k];
				if(di>=1&&di<=n&&dj>=1&&dj<=n&&!a[di][dj]) {
					add(idx[i][j],idx[di][dj]);
					add(idx[di][dj],idx[i][j]);
				}
			}
		}
	}
	for(i=1;i<=n;i++) {
		for(j=1;j<=n;j++) {
			if(i+j&1) {
				tot++;
				if(dfs(idx[i][j])) sum--;
			}
		}
	}
	printf("%d\n",sum);
}

猜你喜欢

转载自www.cnblogs.com/suika/p/9095210.html
今日推荐