bzoj3175 [ TJOI2013 ] -- 二分图最大点独立集
画个图自己走一走,容易看出这是一个二分图。
那么答案就是二分图的最大点独立集。
二分图的最大点独立集=|V|-最大匹配数
最大匹配数用匈牙利算法求。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 #define N 210 6 struct Edge{ 7 int t,nx; 8 }e[N*N<<3]; 9 int xx[8]={-1,-2,1,2,-1,-2,1,2}; 10 int yy[8]={2,1,-2,-1,-2,-1,2,1}; 11 int i,j,k,x,y,Ans,p,q,n,m,v[N*N],Num,Cnt,a[N][N],c[N*N],h[N*N],Sum; 12 bool b[N][N]; 13 char s[N]; 14 inline void Add(int x,int y){ 15 e[++Num].t=y;e[Num].nx=h[x];h[x]=Num; 16 } 17 inline bool Dfs(int x,int y){ 18 if(v[x]==y)return 0;v[x]=y; 19 for(int i=h[x];i;i=e[i].nx) 20 if(c[e[i].t]==0||Dfs(c[e[i].t],y)){ 21 c[e[i].t]=x; 22 return 1; 23 } 24 return 0; 25 } 26 int main() 27 { 28 scanf("%d",&n); 29 for(i=1;i<=n;i++){ 30 scanf("%s",s+1); 31 for(j=1;j<=n;j++){ 32 a[i][j]=++Cnt; 33 if(s[j]=='1')b[i][j]=1,Sum++; 34 } 35 } 36 for(i=1;i<=n;i++) 37 for(j=1;j<=n;j++) 38 if(!b[i][j]) 39 for(k=0;k<8;k++){ 40 x=i+xx[k];y=j+yy[k]; 41 if(x>n||x<1||y>n||y<1||b[x][y])continue; 42 Add(a[i][j],a[x][y]); 43 } 44 for(i=1;i<=Cnt;i++)if(Dfs(i,i))Ans++; 45 printf("%d",Cnt-Sum-(Ans>>1)); 46 return 0; 47 }