[BZOJ1412][ZJOI2009]狼和羊的故事(最小割)
题目描述
传送门
题解
首先建立源汇,对于每一个为1的点s->i,对于每一个为2的点i->t,然后每个点向它的四周连边。
这样做的原因是无论如何狼和羊不能通过任何道路连通。
最小割即为答案。
代码
#include
#include
#include
#include
using namespace std;const int max_n=105;
const int max_N=1e4+5;
const int max_m=2e5+5;
const int max_e=max_m*2;
const int INF=1e9;int n,m,a[max_n][max_n],N,maxflow;
int tot,point[max_N],next[max_e],v[max_e],remain[max_e];
int deep[max_N],last[max_N],num[max_N],cur[max_N];
queue <int> q;inline void addedge(int x,int y,int cap){++tot; next[tot]=point[x]; point[x]=tot; v[tot]=y; remain[tot]=cap;++tot; next[tot]=point[y]; point[y]=tot; v[tot]=x; remain[tot]=0;
}inline void bfs(int t){for (int i=1;i<=N;++i) deep[i]=N; deep[t]=0;while (!q.empty()) q.pop(); q.push(t);while (!q.empty()){int now=q.front(); q.pop();for (int i=point[now];i!=-1;i=next[i])if (deep[v[i]]==N&&remain[i^1]){deep[v[i]]=deep[now]+1;q.push(v[i]);}}
}
inline int addflow(int s,int t){int now=t,ans=INF;while (now!=s){ans=min(ans,remain[last[now]]);now=v[last[now]^1];}now=t;while (now!=s){remain[last[now]]-=ans;remain[last[now]^1]+=ans;now=v[last[now]^1];}return ans;
}
inline void isap(int s,int t){bfs(t);for (int i=1;i<=N;++i) ++num[deep[i]];for (int i=1;i<=N;++i) cur[i]=point[i];int now=s;while (deep[s]if (now==t){maxflow+=addflow(s,t);now=s;}bool has_find=false;for (int i=cur[now];i!=-1;i=next[i])if (deep[v[i]]+1==deep[now]&&remain[i]){has_find=true;cur[now]=i;last[v[i]]=i;now=v[i];break;}if (!has_find){int minn=N-1;for (int i=point[now];i!=-1;i=next[i])if (remain[i]) minn=min(minn,deep[v[i]]);if (!(--num[deep[now]])) break;++num[deep[now]=minn+1];cur[now]=point[now];if (now!=s) now=v[last[now]^1];}}
}
int main(){tot=-1;memset(point,-1,sizeof(point));memset(next,-1,sizeof(next));scanf("%d%d",&n,&m);for (int i=1;i<=n;++i)for (int j=1;j<=m;++j)scanf("%d",&a[i][j]);N=n*m+2;for (int i=1;i<=n;++i)for (int j=1;j<=m;++j){int num=(i-1)*m+j;if (a[i][j]==1) addedge(1,1+num,INF);else if (a[i][j]==2) addedge(1+num,N,INF);if (i!=1){int num1=(i-2)*m+j;addedge(1+num,1+num1,1);}if (j!=1){int num1=num-1;addedge(1+num,1+num1,1);}if (i!=n){int num1=i*m+j;addedge(1+num,1+num1,1);}if (j!=m){int num1=num+1;addedge(1+num,1+num1,1);}}isap(1,N);printf("%d\n",maxflow);
}
总结
网络流再RE撞死算了。
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
