您的位置:首页 > 理论基础 > 计算机网络

[网络流入门,简单题]poj1273Drainage Ditches最大流

2014-07-29 09:44 211 查看
最大流第一题.哦也~~~~~~~~~凭自己的理解写的代码,多做点题,应该会好一点.........

这是EK算法, 根据某网友的描述,该叫"方法",因为实现方式可以多样.最重要的是这个算法的思想. 算法思想源于贪心:

首先从起点开始寻找到终点的可行路,并让其满流.同时建立反向边.比如这题的数据

5条边,4个节点

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

然后我们随便找了一条路1->2->3->4满流流量为10,建立反向边4->3,3->2,2->1流量为10,并且原正向边容量直接减掉10(在各种帖子里,都用神马f,c函数来搞,我都搞晕了)

然后就这样不断地找增广路,建边.最后就得到答案了.这贪心的关键还在于建反向边,有一篇帖子对其中的理解我表示非常敬佩,至少在我看了若干帖子若干博客若干PPT后

都没明白,却因为这篇博客懂了些.参看:http://blog.sina.com.cn/s/blog_6cf509db0100uy5n.html

看完了基本就能理解这算法的奥妙之处了.总之在各种博客各种教学贴中,大家都是一个语调,我了个擦,这让毫无基础的我情何以堪.前几天有个退役的老队员来讲课,我靠,这

尼玛默认我学过图论呐(=@__@=) ............哎哎哎哎,好吧,从简单的入手,一步一步学....

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <climits>
using namespace std;
const int MAX_V = 208;
const int MAX_E = 208;
const int INF = INT_MAX>>2;//INF完全可以自己设置成100万这样子....写INT_MAX是为了装逼

bool vis[MAX_V];	//用于BFS时的标记
int G[MAX_V][MAX_V];	//邻接矩阵,G[i][j]表示从i到j的残余容量,初始为容量
//这里不用f反向边了,而是直接加到原图中
int prev[MAX_V]; //用于BFS保存增广路,前继节点
/*
比如我们找到的增广路是1->2->3->4,当然在我的实现中编号是0->1->2->3,prev数组就会保存成这个
样子: prev[3] = 2, prev[2] = 1, prev[1] = 0, prev[0] = -1;那BFS返回后如果返回值是true就可以直接利用这个数组还原出路径来了.
又比如增广路是0->6->8->19,那数组中应该是:prev[19]=8, prev[8]=6, prev[6]=0,其它都是-1,因为我们知道要找的是0->19的路径,所以我们令p等于19,
然后看一下prev[19]等于多少,等于8,那就说明倒数第二个点就是8,在令p=prev[p],得到6,那我们就知道倒数第三个点是6,然后p=prev[p],倒数第四个点是0,
嘿,就等于起始点了,哈,就说明路径就是19<--8<--6<--0了,注意是反向的哦.BFS过程还是很朴素的,就和普通的广搜一样.
然后还有就是vis数组,当然需要这个标记数组,不然你找到一个环的话,程序就会卡死了,就一直在那个环里打转了
*/
int n, m;

bool BFS(int s, int t) {
queue<int> Q;
memset(vis, false, sizeof(vis));
memset(prev, -1, sizeof(prev));	//no else

Q.push(s);
vis[s] = true;

int now;
while (!Q.empty()) {
now = Q.front(); Q.pop();

for (int i = 0; i < n; ++i) {
if (G[now][i] > 0 && !vis[i]) {
prev[i] = now;
vis[i] = true;
if (i == t) return true;
Q.push(i);
}
}//for
}
return false;
}
/* s到t的最大流 */
int EK(int s, int t) {
int flow = 0; //最大流
int i, j;
while (BFS(s, t)) {
int d = INF, p;
for (p = t; p != s; p = prev[p]) {
d = min(d, G[prev[p]][p]); //d要设置为该路上各段的最小值
}

for (p = t; p != s; p = prev[p]) {
G[prev[p]][p] -= d;
G[p][prev[p]] += d;
}
flow += d;

}
return flow;
}
int main() {
while (~scanf(" %d %d", &m, &n)) {
memset(G, 0, sizeof(G));
int f, t, c;
for (int i = 0; i < m; ++i) {
scanf(" %d %d %d", &f, &t, &c);
G[f-1][t-1] += c;
}

printf("%d\n", EK(0, n-1));
}
return 0;
}
本文完
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: