[洛谷P1343]地震逃生

题目大意:有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;
}

 

posted @ 2017-09-10 19:12  Mrsrz  阅读(198)  评论(0编辑  收藏  举报