洛咕 P4304 [TJOI2013]攻擊裝置
阿新 • • 發佈:2018-10-31
把座標按照(x+y)%2染色可以發現這是個二分圖
二分圖最大獨立集=點數-最大匹配
於是就是個算匹配的傻逼題了
// luogu-judger-enable-o2 #include<bits/stdc++.h> #define il inline #define vd void typedef long long ll; il int gi(){ int x=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')f=-1; ch=getchar(); } while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } char s[210][210]; const int maxn=40010,maxm=2000000; int num[210][210],cnt,S,T; int fir[maxn],dis[maxm],nxt[maxm],w[maxm],id=1,head[maxn],dep[maxn]; il vd link(int a,int b){ nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=1; nxt[++id]=fir[b],fir[b]=id,dis[id]=a,w[id]=0; } const int dX[]={-1,-2,-1,-2,1,2,1,2},dY[]={2,1,-2,-1,2,1,-2,-1}; il bool BFS(){ static int que[maxn],hd,tl; hd=tl=0;que[tl++]=S; memset(dep,0,sizeof dep);dep[S]=1; while(hd^tl){ int x=que[hd++]; for(int i=fir[x];i;i=nxt[i]) if(w[i]&&!dep[dis[i]])que[tl++]=dis[i],dep[dis[i]]=dep[x]+1; } return dep[T]; } il int Dinic(int x,int maxflow){ if(x==T)return maxflow; int ret=0; for(int&i=head[x];i;i=nxt[i]) if(w[i]&&dep[dis[i]]==dep[x]+1){ int d=Dinic(dis[i],std::min(w[i],maxflow-ret)); w[i]-=d,w[i^1]+=d,ret+=d; if(ret==maxflow)break; } return ret; } int main(){ #ifndef ONLINE_JUDGE freopen("4304.in","r",stdin); freopen("4303.out","w",stdout); #endif int n=gi();for(int i=1;i<=n;++i)scanf("%s",s[i]+1); S=++cnt,T=++cnt; int ans=0; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j){ if(s[i][j]=='1')continue; num[i][j]=++cnt;++ans; if((i+j)&1)link(S,num[i][j]); else link(num[i][j],T); } for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(s[i][j]=='0'&&((i+j)&1)) for(int k=0;k<8;++k){ int xx=i+dX[k],yy=j+dY[k]; if(!num[xx][yy])continue; link(num[i][j],num[xx][yy]); } while(BFS())memcpy(head,fir,sizeof fir),ans-=Dinic(S,1e9); printf("%d\n",ans); return 0; }