洛谷P1343 地震逃生
题目地址:https://www.luogu.org/problem/show?pid=1343
这是一道网络流的模板题,介于蒟蒻我才学网络流,决定发表一篇博客进行巩固。
最大流是一种非常基础的网络流,也是学好所有网络流的关键,大家如果不懂可以看一下这篇博客,写得非常好,清晰易懂。
接下来介绍一下Dinic算法,Dinic算法主要是通过BFS建立,然后不断的对当前的分层图进行增广,直到无法在建立可以到达汇点的分层图。
当我们在进行增广时,为了不重复,我们可以把每一次的路径的容量-残量,当容量减到0时,表示这条路已经不可以走了。最后把每一次增广所得的答案求和,便是最大流。
当然也可以流量值+残量,当流量=容量时,退出。大致思路与上一种无异。
代码:
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int MAXN=210; const int MAXM=2010; const int INF=(1<<30); int to[MAXM<<1],next[MAXM<<1],cap[MAXM<<1];//cap表示容量 int head[MAXN],sum_edge; void add_edge(int u,int v,int e) { to[sum_edge]=v;next[sum_edge]=head[u];cap[sum_edge]=e;head[u]=sum_edge++;//使用^操作时要从0开始加边。 to[sum_edge]=u;next[sum_edge]=head[v];cap[sum_edge]=0;head[v]=sum_edge++; } int n,m,x; queue<int>Q; int depth[MAXN]; bool BFS() { memset(depth,-1,sizeof(depth)); depth[1]=0; Q.push(1); while(!Q.empty()) { int u=Q.front(); Q.pop(); for(int i=head[u];i!=-1;i=next[i]) { int v=to[i]; if(cap[i]&&depth[v]<0)//cap[i]要>0 { depth[v]=depth[u]+1; Q.push(v); } } } return depth[n]==-1?0:1; } int DFS(int u,int mxf) { if(u==n||mxf<=0) return mxf; int flow=0,f; for(int i=head[u];i!=-1;i=next[i]) { int v=to[i]; if(depth[v]==depth[u]+1&&(f=DFS(v,min(mxf,cap[i])))>0) { cap[i]-=f; cap[i^1]+=f; flow+=f; mxf-=f; if(mxf<=0) break; } } return flow; } int Dinic() { int ret=0; while(BFS()) ret+=DFS(1,INF); return ret; } int main() { memset(head,-1,sizeof(head)); scanf("%d%d%d",&n,&m,&x); for(int i=1,u,v,e;i<=m;i++) { scanf("%d%d%d",&u,&v,&e); add_edge(u,v,e); } int mx=Dinic(); if(!mx) puts("Orz Ni Jinan Saint Cow!"); else printf("%d %d",mx,x/mx+(x%mx?1:0)); return 0; }