独立集。
对于一个无向图,要求他的最大独立集,这是个npc问题,无法在多项式时间内得出答案,退而求其次,我们只能找到一些特殊图的最大独立集的多项式解法。
1.树。
这是一个比较好求的,有两种办法,一种是贪心,一种是动归,都是O(N)的,贪心暂时不会,也没准备会,动归简单:f[i][0]表示第i个不取,他与他的儿子得到的最大答案,f[i][1]表示第i个要取,他与他的儿子得到的最大答案。
f[i][0]=sum{max{f[son[i]][0],f[son[i]][1]}};
f[i][1]=sum{f[son[i]][0]}+1;
2.二分图。
这个也好求,ans=总点数-最大匹配数。
做一遍二分图匹配就行了。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <ctime>
#include <iostream>
#include <algorithm>
#define maxn 1000020
using namespace std;
int n;
char st[2000][200];
int x[8]={-1,-2,1,2,-1,-2,1,2};
int y[8]={-2,-1,-2,-1,2,1,2,1};
int tot=1;
int fir[maxn],en[maxn],nex[maxn],f[maxn];
inline void ins(int x,int y,int z){
// printf("%d %d %d\n",x,y,z);
nex[++tot]=fir[x];
fir[x]=tot;
en[tot]=y;
f[tot]=z;
nex[++tot]=fir[y];
fir[y]=tot;
en[tot]=x;
f[tot]=0;
}
int s,t;
int flog=0,sum=0;
int now[maxn],pre[maxn],his[maxn],num[maxn],d[maxn];
inline void sap(){
flog=0;
for (int i=0;i<=t;i++){
now[i]=fir[i];
num[i]=d[i]=0;
}
num[0]=sum;
int i=s;
bool flag;
int aug=0x7fffffff/10;
while (d[s]<sum){
flag=false;
his[i]=aug;
for (int k=now[i];k;k=nex[k]){
int j=en[k];
if ((d[i]==d[j]+1)&&(f[k]>0)){
now[i]=k;
pre[j]=i;
flag=true;
if (aug>f[k]) aug=f[k];
i=j;
if (i==t){
flog+=aug;
while (i!=s){
i=pre[i];
f[now[i]]-=aug;
f[now[i]^1]+=aug;
}
aug=0x7fffffff/10;
}
break;
}
}
if (flag) continue;
int k1=0,minn=sum;
for (int k=fir[i];k;k=nex[k])
if (f[k]>0&&minn>d[en[k]]){
minn=d[en[k]];
k1=k;
}
--num[d[i]];
if (num[d[i]]==0) return;
d[i]=minn+1;
++num[d[i]];
now[i]=k1;
if (i!=s){
i=pre[i];
aug=his[i];
}
}
}
int main(){
// freopen("3175.in","r",stdin);
// freopen("3175.out","w",stdout);
scanf("%d\n",&n);
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
scanf("%c",&st[i][j]);
if (st[i][j]=='0')
sum++;
}
getchar();
}
s=0;t=n*n+1;
sum=sum+2;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
if (st[i][j]=='0'){
if ((i+j)%2==1){
ins(s,(i-1)*n+j,1);
for (int p=0;p<8;p++)
if (i+x[p]>=1&&i+x[p]<=n)
if (j+y[p]>=1&&j+y[p]<=n)
if (st[i+x[p]][j+y[p]]=='0')
ins((i-1)*n+j,(i+x[p]-1)*n+j+y[p],0x7fffffff/10);
}
else ins((i-1)*n+j,t,1);
}
sap();
printf("%d",sum-2-flog);
return 0;
}