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); }