您的位置:首页 > 大数据 > 人工智能

USACO-Section 4.2 Drainage Ditches (最大流[Ford-Fulkerson])

2016-04-17 12:19 591 查看


描述

在农夫约翰的农场上,每逢下雨,贝茜最喜欢的三叶草地就积聚了一潭水。这意味着草地被水淹没了,并且小草要继续生长还要花相当长一段时间。因此,农夫约翰修建了一套排水系统来使贝茜的草地免除被大水淹没的烦恼(不用担心,雨水会流向附近的一条小溪)。作为一名一流的技师,农夫约翰已经在每条排水沟的一端安上了控制器,这样他可以控制流入排水沟的水流量。

农夫约翰知道每一条排水沟每分钟可以流过的水量,和排水系统的准确布局(起点为水潭而终点为小溪的一张网)。需要注意的是,有些时候从一处到另一处不只有一条排水沟。

根据这些信息,计算从水潭排水到小溪的最大流量。对于给出的每条排水沟,雨水只能沿着一个方向流动,注意可能会出现雨水环形流动的情形。


格式

PROGRAM NAME:ditch

INPUT FORMAT:

(file ditch.in)

第1行: 两个用空格分开的整数N (0 <= N <= 200) 和 M (2 <= M <= 200)。N是农夫John已经挖好的排水沟的数量,M是排水沟交叉点的数量。交点1是水潭,交点M是小溪。

第二行到第N+1行: 每行有三个整数,Si, Ei, 和 Ci。Si 和 Ei (1 <= Si, Ei <= M) 指明排水沟两端的交点,雨水从Si 流向Ei。Ci (0 <= Ci <= 10,000,000)是这条排水沟的最大容量。

OUTPUT FORMAT:

(file ditch.out)

输出一个整数,即排水的最大流量。


SAMPLE INPUT

5 4
1 2 40
1 4 20
2 4 20
2 3 30
3 4 10


SAMPLE OUTPUT

50


重见好久不见的1次AC

看了前面的算法介绍和网上的算法讲解,明白了网络流的求法,然后按照算法写了一遍

用bfs找增广路径,寻找增光路径时找当前路径流量最大的一条,然后进行图的更新,直至无法到达汇点

原来Edmonds-Karp算法是建立在Ford-Fulkerson方法上的增广路算法,与一般的Ford-Fulkerson算法不同的是,它用广度搜索实现对增广路的寻找,只是BFS的别称吧...

感觉不会称呼算法了...

/*
ID: your_id_here
PROG: ditch
LANG: C++
*/
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>

using namespace std;

const int INF=0x3f3f3f3f;

int n,m,g[205][205],pre[205];
bool vis[205];

struct Node {
int pre,u,mn;//u表示当前节点,mn表示从源点到该点的流量上限中最小的

Node(int ppre=0,int uu=0,int mmn=INF):pre(ppre),u(uu),mn(mmn) {}

bool operator < (const Node& a) const {
return mn<a.mn;
}
}cur;

int bfs(int sta,int des) {//用bfs找到流量最大的一条增广路径,并返回这条增广路径的流量
memset(vis,false,sizeof(vis));
priority_queue<Node> q;
q.push(Node(0,sta));
while(!q.empty()) {
do {
cur=q.top();
q.pop();
} while(!q.empty()&&vis[cur.u]);
if(vis[cur.u])//如果无法到达汇点,返回0
return 0;

vis[cur.u]=true;
pre[cur.u]=cur.pre;
if(cur.u==des)
return cur.mn;
for(int i=1;i<=n;++i) {//枚举可流向的下一个点
if(!vis[i]&&g[cur.u][i]!=0) {
q.push(Node(cur.u,i,min(cur.mn,g[cur.u][i])));
}
}
}
return 0;
}

int Ford_Fulkerson(int sta,int des) {
int mn,e,ans=0;
while(mn=bfs(sta,des),mn!=0) {//当可增加的流量不为0时,继续算法
ans+=mn;
e=des;
while(e!=sta) {
g[pre[e]][e]-=mn;//正向的边减去相应的流量
g[e][pre[e]]+=mn;//反向的边加上相应的流量
e=pre[e];
}
}
return ans;
}

int main() {
freopen("ditch.in","r",stdin);
freopen("ditch.out","w",stdout);

int s,e,w;
memset(g,0,sizeof(g));
scanf("%d%d",&m,&n);
while(m-->0) {
scanf("%d%d%d",&s,&e,&w);
g[s][e]+=w;
}
printf("%d\n",Ford_Fulkerson(1,n));

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: