题解:
最大独立集=最小边覆盖=总点数-最大匹配数
所以就把每个点和可以被他打的点标记一下,
跑一遍匈牙利。
代码:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define get(i,j) (i-1)*n+j
const int N=205;
int n,ans=0;
char s[N][N];
//bool ma[N*N][N*N];
vector<int>q[N*N];
int pi[8][2]={-1,-2,-2,-1,1,-2,2,-1,-1,2,-2,1,1,2,2,1};
int match[N*N];
bool tf[N*N];
bool get_ans(int x)
{
int yu;
for(int i=q[x].size()-1;i>=0;i--)
{
yu=q[x][i];
if(tf[yu])
{
tf[yu]=0;
if(match[yu]==0||get_ans(match[yu])==true)
{
match[yu]=x;
return true;
}
}
}
return false;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);//printf("!");
//memset(ma,0,sizeof(ma));
//printf("%d",ma[1][1]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(s[i][j]=='0')
{
ans++;
for(int u=0;u<8;u++)
{
int tx=i+pi[u][0],ty=j+pi[u][1];
if(tx>n||ty>n||tx<1||ty<1||s[tx][ty]=='1') continue;
q[get(i,j)].push_back(get(tx,ty));
}
}
}
}
memset(match,0,sizeof(match));
int sum=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
memset(tf,true,sizeof(tf));
if(get_ans(get(i,j))==true) sum++;
}
}
printf("%d\n",ans-sum/2);
}
关于二分图: