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

浙公网安备 33010602011771号