[BZOJ 1412] 狼与羊的故事
Link:
Solution:
非常明显的最小割模型:
将所有点分成两个互不相邻的点集,且要求代价最小
建图:
$<S,sheep,INF>$
$<wolf,T,INF>$
$<sheep,wolf/ground,1>$、$<ground,wolf/sheep/ground,1>$
Code:
#include <bits/stdc++.h> using namespace std; const int MAXN=10005,MAXM=40005,INF=1<<27; namespace Max_Flow { int head[MAXN],S,T,level[MAXN],iter[MAXN],tot=-1; struct edge{int nxt,to,cap;}e[MAXM<<2]; void add_edge(int from,int to,int cap) { e[++tot].nxt=head[from];e[tot].to=to;e[tot].cap=cap;head[from]=tot; e[++tot].nxt=head[to];e[tot].to=from;e[tot].cap=0;head[to]=tot; } bool bfs() { memset(level,-1,sizeof(level)); queue<int> q;q.push(S);level[S]=0; while(!q.empty()) { int u=q.front();q.pop(); for(int i=head[u];i!=-1;i=e[i].nxt) if(e[i].cap && level[e[i].to]==-1) level[e[i].to]=level[u]+1,q.push(e[i].to); } return (level[T]!=-1); } int dfs(int v,int f) { if(v==T) return f; int ret=0; for(int &i=iter[v];i!=-1;i=e[i].nxt) { if(level[e[i].to]==level[v]+1 && e[i].cap) { int d=dfs(e[i].to,min(f,e[i].cap)); e[i].cap-=d;e[i^1].cap+=d; f-=d;ret+=d;if(!f) break; } } return ret; } int Dinic() { int ret=0; while(bfs()) { for(int i=0;i<MAXN;i++) iter[i]=head[i]; ret+=dfs(S,INF); } return ret; } } int dx[]={1,-1,0,0},dy[]={0,0,1,-1}; int n,m,dat[105][105]; int main() { using namespace Max_Flow; S=0;T=10001;memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) scanf("%d",&dat[i][j]); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(dat[i][j]==1) add_edge(S,(i-1)*m+j,INF); if(dat[i][j]==2){add_edge((i-1)*m+j,T,INF);continue;} for(int k=0;k<4;k++) { int fx=i+dx[k],fy=j+dy[k]; if(fx<1||fx>n||fy<1||fy>m) continue; if(dat[i][j]!=1 || dat[fx][fy]!=1) add_edge((i-1)*m+j,(fx-1)*m+fy,1); } } printf("%d",Dinic()); return 0; }