[POJ 1273] Drainage Ditches 最大流 模板题

题目传送门:【BZOJ 1273】


题目大意:Farmer John 担心他的三叶草被雨淋坏了,于是他修建了许多的排水沟将雨引到附近的一条小溪中。作为一名优秀的工程师,他有办法控制通过排水沟的水量。他不仅知道排水沟每分钟能运走多少水,还清楚它的详细结构。这些排水沟连接着一旁的池塘和小溪。现在,他想问你,这个排水沟将水从池塘引向小溪所允许的最大流量是多少。

输入多组数据,每组数据的第一行包含两个整数 N 和 M,分别代表排水沟的边数和节点数量。1 号节点是池塘,m 号节点是小溪。接下来 N 行,每行三个整数 Si,Ei,Ci,表示水沟从 Si 流向 Ei,以及这条水沟所允许的最大流量 Ci。输出则为从池塘流向小溪的流量的最大值。


题目分析:

一道最大流的模板题。

题目的暗示性已经非常清楚了。将 1 号节点设为源点 S,m 号节点设为汇点 T,Ci 作为每条边的容量。然后直接套最大流的算法即可(Edmonds-Karp,Dinic,ISAP 等)。


下面附上 Dinic 的代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
const int MX=20005;
const int INF=0x3f3f3f3f;

struct Edge{
	int to,cap,next;
};
Edge edge[2 * MX];
int n,m,head[MX],now = 1,dis[MX];

void adde(int u,int v,int c){
	edge[++now].to = v;
	edge[now].cap = c;
	edge[now].next = head[u];
	head[u] = now;
}

bool bfs(int s){
	queue<int> q;
	bool vis[MX] = {0};
	q.push(s);
	dis[s] = 0;
	vis[s] = true;
	while (!q.empty()){
		int u = q.front();
		q.pop();
		for (int i = head[u];i;i = edge[i].next){
			int v = edge[i].to;
			if (!vis[v] && edge[i].cap){
				dis[v] = dis[u]+1;
				vis[v] = true;
				q.push(v);
			}
		}
	}
	if (vis[m])
		return true;
	return false;
}

int dfs(int u,int delta){
	if (u == m) return delta;
	int sum=0;
	for (int i = head[u];i && delta;i = edge[i].next){
		int v = edge[i].to;
		if (edge[i].cap && dis[v] == dis[u] + 1){
			int d = dfs(v, min(edge[i].cap,delta) );
			edge[i].cap -= d;
			edge[i ^ 1].cap += d;
			delta -= d;
			sum += d;
		}
	}
	return sum;
}

int getFlow(){
	int ans = 0;
	while (bfs(1)){
		ans += dfs(1,INF);
		memset(dis,0x3f,sizeof(dis));
	}
	return ans;
}

int main(){
	int Si,Ei,Ci;
	while (scanf("%d%d",&n,&m) != EOF){
		memset(head,0,sizeof(head));
		memset(edge,0,sizeof(edge));
		memset(dis,0x3f,sizeof(dis));
		for (int i = 1;i <= n;i++){
			scanf("%d%d%d",&Si,&Ei,&Ci);
			adde(Si,Ei,Ci);
			adde(Ei,Si,0);
		}
		printf("%d\n",getFlow());
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值