题目大意:有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\n",mf,(long long)x/mf+(x%mf>0));else
puts("Orz Ni Jinan Saint Cow!");
return 0;
}