比较裸的二分图最大独立集,不过复杂度是不对的,匈牙利算法跑得太快了,然后要注意为了不超时,每次匈牙利的时候不能清空vis的数组,而是把它进行标记。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#define maxn 40010
#define maxm 8*40010
using namespace std;
int head[maxn],next[maxm],to[maxm];
int lk[maxn];
int a[210][210];
int dx[4]={1,1,2,2};
int dy[4]={2,-2,1,-1};
int n,m,num,cnt,ans,T;
int vis[maxn];
char s[210];
bool find(int x)
{
for (int p=head[x];p;p=next[p])
if (vis[to[p]]!=T)
{
vis[to[p]]=T;
if (!lk[to[p]] || find(lk[to[p]]))
{
lk[to[p]]=x;
return 1;
}
}
return 0;
}
void addedge(int x,int y)
{
num++;to[num]=y;next[num]=head[x];head[x]=num;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%s",s+1);
for (int j=1;j<=n;j++)
{
if (s[j]=='0') a[i][j]=++cnt;
else a[i][j]=0;
}
}
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (a[i][j])
{
for (int k=0;k<4;k++)
{
int x=i+dx[k],y=j+dy[k];
if (x<1 || x>n || y<1 || y>n) continue;
if (a[x][y]) addedge(a[i][j],a[x][y]),addedge(a[x][y],a[i][j]);
}
}
for (int i=1;i<=cnt;i++)
{
T++;
if (find(i)) ans++;
}
printf("%d\n",cnt-ans/2);
return 0;
}