BZOJ 4808: 马(二分图最大点独立集)
http://www.lydsy.com/JudgeOnline/problem.php?id=4808
题意:
思路:
这图中的两个马只能选一个,二选一,很像二分图吧,对能互吃的两个棋子连线,在所选的任意两个棋子中,都不能互相有连线,这不就是最大点独立集吗?
最大独立集 = 顶点个数 - 最大匹配。记得把坏了的格子去掉。
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n,m,tot; int mp[205][205], head[40005], mark[40005]; bool vis[40005]; struct node { int v,next; }e[8*40005]; int dx[] = {-2,-2,-1,-1,1,1,2,2}; int dy[] = {1,-1,2,-2,2,-2,1,-1}; void addEdge(int u, int v) { e[tot].v = v; e[tot].next = head[u]; head[u] = tot++; } bool match(int u) { for(int i=head[u];i!=-1;i=e[i].next) { int v = e[i].v; if(!vis[v]) { vis[v] = true; if(mark[v]==-1 || match(mark[v])) { mark[v] = u; return true; } } } return false; } int main() { //freopen("in.txt","r",stdin); int num = 0; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { scanf("%d",&mp[i][j]); if(mp[i][j]) num++; } tot = 0; memset(head,-1,sizeof(head)); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(!mp[i][j]) { for(int k=0;k<8;k++) { int x = i+dx[k]; int y = j+dy[k]; if(x<1 || x>n || y<1 || y>m) continue; if(mp[x][y]==1) continue; int p1 = (i-1)*m+j; int p2 = (x-1)*m+y; addEdge(p1,p2); } } } int sum = 0; memset(mark,-1,sizeof(mark)); for(int i=1;i<=n*m;i++) { memset(vis,false,sizeof(vis)); if(match(i)) sum++; } printf("%d\n",n*m-num-sum/2); return 0; }