http://www.lydsy.com/JudgeOnline/problem.php?id=1412
超级源点连向所有的狼,超级汇点连向所有羊,流量为INF
相邻连边流量为1,最小割
#include<cstdio> #include<queue> #include<cstring> #include<algorithm> std::queue<int>que; int fs[5]={0,1,0,-1,0}; #define INF 0x7fffffff const int maxn = 300007; int map[1007][1007]; inline int read() { int x=0; char c=getchar(); while(c<'0'||c>'9')c=getchar(); while(c<='9'&&c>='0')x=x*10+c-'0',c=getchar(); return x; } int n,m,S,T,src,decc; struct node{ int v,next,flow; }edge[maxn];int head[maxn],num=1,cur[maxn],lev[maxn]; void add_edge(int u,int v,int w) { edge[++num].v=v;edge[num].next=head[u];head[u]=num; edge[num].flow=w; } bool bfs() { while(!que.empty()) que.pop(); std::memset(lev,-1,sizeof lev); memcpy(cur,head,sizeof head); lev[src]=0; que.push(src);int now; while(!que.empty()) { now=que.front();que.pop(); for(int i=head[now];i;i=edge[i].next) { int v=edge[i].v; if(lev[v]==-1&&edge[i].flow>0) { lev[v]=lev[now]+1; if(v==decc)return true; que.push(v); } } } return false; } int dfs(int now,int flow) { if(now==decc)return flow; int rest=0,delta; for(int &i=cur[now];i;i=edge[i].next) { int v=edge[i].v; if(lev[v]==lev[now]+1&&edge[i].flow>0) { delta=dfs(v,std::min(flow-rest,edge[i].flow)); if(delta) { edge[i].flow-=delta; edge[i^1].flow+=delta; rest+=delta;if(rest==flow)break; } } } if(rest==flow)lev[now]=-1;//满流 return rest; } int Dinic() { int ans=0; while(bfs()) ans+=dfs(src,INF); return ans; } inline void add(int a,int b,int flow) { add_edge(a,b,flow);add_edge(b,a,0); } inline int calc(int i,int j) { return (i-1)*m+j; } int main() { n=read(),m=read(); src=0;decc=n*m+1; for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) map[i][j]=read(); for(int i=1;i<=n;++i) { for(int j=1;j<=m;++j) { if(map[i][j]==1)add(src,calc(i,j),INF); else if(map[i][j]==2){ add(calc(i,j),decc,INF);continue;} for(int k=0;k<4;++k) { int x=i+fs[k],y=j+fs[k+1]; if(x<=0||x>n||y<=0||y>m)continue; add(calc(i,j),calc(x,y),1); } } } printf("%d ",Dinic()); return 0; }