依照题目要求,即是不能从2流到1去,那么就是最小割。
从2向0,1连边,从0向0,1连边,然后跑最大流。
代码如下:
#include<bits/stdc++.h> using namespace std; #define inf 1e9 const int maxn=105; const int maxm=5*1e4+5; int n,m,a[maxn][maxn]; int beg[maxm],nex[maxm],to[maxm],w[maxm],e; inline void add(int x,int y,int z){ nex[e]=beg[x];beg[x]=e; to[e]=y;w[e]=z;e++; } inline int read(){ int x=0;char c=getchar(); while(c<'0'||c>'9')c=getchar(); while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-'0';c=getchar();} return x; } int dx[4]={0,0,1,-1}; int dy[4]={1,-1,0,0}; inline int get(int x,int y){return (x-1)*m+y;} int dep[maxm]; queue<int>q; inline int bfs(){ memset(dep,0x3f,sizeof(dep)); while(!q.empty())q.pop(); dep[0]=0;q.push(0); while(!q.empty()){ int x=q.front(); q.pop(); for(int i=beg[x];~i;i=nex[i]){ int t=to[i]; if(w[i]&&dep[t]>maxn){ dep[t]=dep[x]+1; q.push(t); } } } return dep[n*m+1]<maxn; } inline int dfs(int x,int lim){ if(x==n*m+1||!lim)return lim; int ans=0; for(int i=beg[x];~i;i=nex[i]){ int t=to[i]; if(w[i]&&dep[t]==dep[x]+1){ int f=dfs(t,min(w[i],lim)); w[i]-=f;w[i^1]+=f; lim-=f;ans+=f; } } return ans; } int main(){ memset(beg,-1,sizeof(beg)); n=read();m=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=read(); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ if(a[i][j]==1){ add(get(i,j),n*m+1,inf); add(n*m+1,get(i,j),0); continue; } if(a[i][j]==2){ add(0,get(i,j),inf); add(get(i,j),0,0); } for(int k=0;k<4;k++){ int xx=i+dx[k]; int yy=j+dy[k]; if(xx<1||yy<1||xx>n||yy>m) continue; if(a[xx][yy]!=2){ add(get(i,j),get(xx,yy),1); add(get(xx,yy),get(i,j),0); } } } int maxflow=0; while(bfs())maxflow+=dfs(0,inf); printf("%d ",maxflow); return 0; }
深深地感到自己的弱小。