题目大意:有n个点m条单向边,每条边有一个容量。现有x人要分批从1走到n,问每批最多能走多少人,分几批运完(或输出无法运完)。
解题思路:一看就是网络流的题目。每批最多能走多少人,即最大流。分几批运完,除一下即可。当最大流为0时无法运完。
以下是Dinic算法的代码(为什么我那么喜欢用Dinic?因为我个人认为它好写!):
C++ Code:
#include<cstdio> #include<queue> #include<cstring> using namespace std; struct edges{ int from,to,cap,nxt; }e[20000]; int cnt,n,m,x,head[202],level[202],iter[202]; void addedge(int from,int to,int cap){ e[++cnt]=(edges){from,to,cap,head[from]}; head[from]=cnt; e[++cnt]=(edges){to,from,0,head[to]}; head[to]=cnt; } queue<int>q; void bfs(int s,int t){ level[s]=0; q.push(s); while(!q.empty()){ int u=q.front(); q.pop(); for(int i=head[u];i;i=e[i].nxt){ int v=e[i].to; if(e[i].cap>0&&level[v]<0){ level[v]=level[u]+1; q.push(v); } } } } long long dfs(int u,int t,long long f){ if(u==t)return f; for(int& i=iter[u];i;i=e[i].nxt){ int v=e[i].to; if(e[i].cap>0&&level[u]<level[v]){ long long d=dfs(v,t,(f>e[i].cap)?(e[i].cap):(f)); if(d){ e[i].cap-=d; e[i^1].cap+=d; return d; } } } return 0; } long long max_flow(int s,int t){ long long flow=0; while(1){ memset(level,-1,sizeof level); bfs(s,t); if(level[t]<0)return flow; memcpy(iter,head,sizeof iter); long long f; if(f=dfs(s,t,0x3f3f3f3f3f3f3f3f))flow+=f; } } int main(){ memset(head,0,sizeof head); memset(e,0,sizeof e); cnt=1; scanf("%d%d%d",&n,&m,&x); while(m--){ int a,b,c; scanf("%d%d%d",&a,&b,&c); addedge(a,b,c); } long long mf=max_flow(1,n); if(mf)printf("%lld %d ",mf,(long long)x/mf+(x%mf>0));else puts("Orz Ni Jinan Saint Cow!"); return 0; }