从狼向空格或羊剪边,从空格向空格或羊建边,最大流最小割
最大流dinic打法(这里用了当前弧优化)
#include<cstdio> #include<cctype> #include<queue> #include<cstring> #define maxn 10002 #define inf 0x3ffffff using namespace std; int n,m,ans,S,T,cnt,cur[maxn],dep[maxn],head[maxn],nex[maxn<<4],to[maxn<<4],w[maxn<<4],s[102][102]; int bzx[]={0,1,0,-1},bzy[]={1,0,-1,0}; inline void read(int &x){ char ch=getchar();x=0;int f=1; while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} x*=f; } inline void addedge(int u,int v,int wi){nex[cnt]=head[u];to[cnt]=v;w[cnt]=wi;head[u]=cnt++;nex[cnt]=head[v];to[cnt]=u;w[cnt]=0;head[v]=cnt++;} inline int bfs(){ queue<int>q;while(!q.empty())q.pop(); memset(dep,0,sizeof dep);dep[S]=1;q.push(S); while(!q.empty()){ int u=q.front();q.pop(); for(int i=head[u];~i;i=nex[i]){ int v=to[i]; if(w[i]>0 && dep[v]==0){ dep[v]=dep[u]+1; q.push(v); } } } return dep[T]!=0; } inline int dfs(int u,int flow){ if(u==T)return flow; int ans=0,x=0; for(int &i=cur[u];~i;i=nex[i]){ int v=to[i]; if(w[i]>0 && dep[v]==dep[u]+1){ x=dfs(v,min(flow-ans,w[i])); w[i]-=x;w[i^1]+=x; ans+=x; if(ans==flow)return flow; } } if(ans==0)dep[u]=0; return ans; } inline void dinic(){ while(bfs()){ for(int i=S;i<=T;i++)cur[i]=head[i];ans+=dfs(S,inf); } } int main(){ memset(head,-1,sizeof head); read(n);read(m);S=0;T=n*m+1; for(int i=1;i<=n;i++)s[i][0]=s[i][m+1]=-1; for(int i=1;i<=m;i++)s[0][i]=s[n+1][i]=-1; for(int i=1;i<=n;i++)for(int j=1;j<=m;j++){ read(s[i][j]); if(s[i][j]==2)addedge(S,(i-1)*m+j,inf);if(s[i][j]==1)addedge((i-1)*m+j,T,inf); } for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)for(int k=0;k<4;k++){ if((s[i][j]==2 ||s[i][j]==0) && (s[i+bzx[k]][j+bzy[k]]==1 || s[i+bzx[k]][j+bzy[k]]==0))addedge((i-1)*m+j,(i+bzx[k]-1)*m+j+bzy[k],1); } dinic(); printf("%d",ans); return 0; }