图论 最大流EK算法

今天接触了最大流,网上有很多ppt,耐心看下,再敲几遍代码大概就能懂意思了

EK 算法

关键是要理解要理解反悔的这个意思,因为每次当你选择了一种方式,但是这种方式不一定是最优的所以我们要再来建立一条反向边,

来完成反悔的策略

然后就是大概一直找增广路,改变最大的值,一直到找不到增广路为止

现在把模板的代码附上,并且给予注释

下面有两种方式一种是紫书上刘汝佳的代码,还有种是用链式前向星,还有种是dfs的方式,之后会继续补充

分别给出两种代码

struct Edge{

int from,to,cap,flow;

// from:起始边, to:终点边 , cap: 容量 , flow: 流量

Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}//内建函数

};

struct EdmondsKarp{

int n,m;

vector<Edge> edges;// edges 用来存所有的边, 正向反向边都要存

vector<int> G[maxn];//用来记录第i个点的每条边的序号

int a[maxn];//用来存增广路上的可改变的值

int p[maxn];// 用来记录入-编号

void init(int n){

for(int i=0;i<n;i++)G[i].clear();

edges.clear();

}

void Addedge(int from, int to ,int cap){

// 边的添加很有技巧

因为可以反悔,所以 我们每次要存入反向边,反向边的容量为0

当然有时候,根据题意的不同有时反向边的容量不为0,那么就按照题目的给的数据进行存储

edges.push_back(Edge(from, to, cap, 0));

edges.push_back(Edge(to, from, 0, 0));

m = edges.size();

// 这个也有技巧,其实这个和链式前向星很像(两条变的存储cnt++,但也是连在一起的,这个也是)

每次将这个点连接的边的序号push进去

G[from].push_back(m-2);

G[to].push_back(m-1);

}

int maxflow(int s,int t){

int flow = 0;

for(;;){

CLR(a);

queue<int> Q;

Q.push(s);

a[s]=inf;

while(!Q.empty()){

int x = Q.front();

Q.pop();

for(int i=0;i<G[x].size();i++){

//访问这个点中的所有边

Edge& e = edges[G[x][i]];

// e得到这个边的信息

if(!a[e.to] && e.cap>e.flow){

//这个部分比较难理解

!a[e.to]最小残留量为0是才会更新,如果已经不为0说明更新过不再更新

当前的容量必须大于流量

p[e.to]=G[x][i];

// 储存当前点的标号,用以后面更新

a[e.to]=min(a[x],e.cap-e.flow);

Q.push(e.to);

}

}

if(a[t])break;//如果被更新break

}

if(!a[t])break;

//此时找不到增广路

for(int u=t;u != s;u = edges[p[u]].from){

edges[p[u]].flow += a[t];

edges[p[u]^1].flow -= a[t];

}

flow += a[t];

}

return flow;

}

};

下面给出用链式前向星代码

void addedge(int u,int v,int w){//这边就是一个简单的链式前向星处理

pnt[cnt]=v;

nxt[cnt]=head[u];

cap[cnt]=w;

head[u]=cnt++;

}

void adddouble(int u,int v,int w){//同样是加边,两条

addedge(u,v,w);

addedge(v,u,0);

}

int maxflow(int s,int t){

int flow = 0;

for(;;){

CLR(a);

queue<int> q;

q.push(s);

a[s]=inf;//不要忘记初始化为inf

while(!q.empty()){

int u = q.front();

q.pop();

for(int i=head[u]; ~i; i= nxt[i]){

int v =pnt[i];

if(!a[v] && cap[i] > 0){

a[v]=min(cap[i],a[u]);

pre[v]=i;// 此时的pre也是记录当前点的标号,记住用链式前向星的时候这是i!

q.push(v);

}

}

if(a[t])break;

}

if(!a[t])break;

flow += a[t];

for(int i,u=t;u!=s;u = pnt[i^1]){// 这部分的更新也是。要对链式前向星理解才行呢!

i = pre[u];

cap[i] -= a[t];//此时我省略了流量,只用了流量所以加减就是反着的,理解理解

cap[i^i] += a[t];

}

}

return flow;

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-08 22:09:33

图论 最大流EK算法的相关文章

HDU 3549 Flow Problem ( 最大流 -EK 算法)

C++,G++的读取速度差距也太大了 Flow Problem 题意:n,m表示n个点m条有向带权边 问:从1-n最大流多少 裸最大流,拿来练手,挺不错的 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <queue> #include <algorithm> const int N = 210; #define

POJ1273 最大流 EK算法

套了个EK的模板 //#pragma comment(linker, "/STACK:16777216") //for c++ Compiler #include <stdio.h> #include <iostream> #include <climits> #include <cstring> #include <cmath> #include <stack> #include <queue> #i

【转】网络最大流——EK算法详解

原文  http://blog.csdn.net/a1dark/article/details/11177907 EdmondsKarp算法,简称EK算法,O(m^2n) 因为是初学教程,所以我会尽量避免繁杂的数学公式和证明.也尽量给出了较为完整的代码.本文的目标群体是网络流的初学者,尤其是看了各种NB的教程也没看懂怎么求最大流的小盆友们.本文的目的是,解释基本的网络流模型,最基础的最大流求法,即bfs找增广路法,也就是EK法,全名是Edmond-Karp,其实我倒是觉得记一下算法的全名和来历可

最大流 EK算法 (转)

反复寻找源点s到汇点t之间的增广路径,若有,找出增广路径上每一段[容量-流量]的最小值delta,若无,则结束. 在寻找增广路径时,可以用BFS来找,并且更新残留网络的值(涉及到反向边). 而找到delta后,则使最大流值加上delta,更新为当前的最大流值. (粗体表明需要掌握的概念) 关于反向边: 以下摘至HDOJ的课件和网上的: 首先来看一下基本的网络流最大流模型. 有n个点,有m条有向边,有一个点很特殊,只出不进,叫做源点,通常规定为1号点.另一个点也很特殊,只进不出,叫做汇点,通常规定

最大流EK算法模板

最近学了下最大流算法,大概思想算是懵懵懂懂了,现在想把模板记录下来,以备后面深刻学习之用. 1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 5 #define _clr(x, y) memset(x, y, sizeof (x)) 6 #define Min(x, y) (x < y ? x : y) 7 #define INF 0x3f3f3f3f 8 #define N 210 9 10 in

【转】最大流EK算法

转自:http://www.cnblogs.com/kuangbin/archive/2011/07/26/2117636.html 图-1 如图-1所示,在这个运输网络中,源点S和汇点T分别是1,7,各边的容量为C(u,v).图中红色虚线所示就是一个可行流.标准图示法如图-2所示: 其中p(u,v) / c(u,v)分别表示该边的实际流量与最大容量. 关于最大流 熟悉了什么是网络流,最大流也就很好理解了.就是对于任意的u∈V-{s},使得p(s,u)的和达到最大.上面的运输网络中,最大流如图-

最大流——EK算法

一.算法理论 [基本思想] 在网络中找增广路径,找到一条增广路径就计算这条路径可已通过的最大流,即瓶颈边的容量.然后修改这条路径上的每条边的容量,如果在路径上就减去刚求出来的流量加上流量其他的边的容量不变.然后在这个残留网路上在搜一条增广路径,直到没有增广路径为止. 一直找增广路径(BFS),假如有,记录增广路的最小值k,ans +=k ,并更新网络的值(要用反向边). [算法详解] 点击

排涝 网络流--最大流 ek算法

传送门: 以前没接触过最大流问题,刚开始以为是用kruscal算法求最小生成树呢,并且题上也是显示最小树的专题: 反正还行吧,捣鼓了两天,总算稍微理解了一下,等会回来整理一下知识点. 1 #include <iostream> 2 #include <queue> 3 #include <algorithm> 4 #include <cstring> 5 #include <cstdio> 6 using namespace std; 7 con

HDU 1532 Drainage Ditches(最大流 EK算法)

题目网址:http://acm.hdu.edu.cn/showproblem.php?pid=1532 思路: 网络流最大流的入门题,直接套模板即可~ 注意坑点是:有重边!!读数据的时候要用"+="替换"=". 对网络流不熟悉的,给一篇讲解:http://www.cnblogs.com/ZJUT-jiangnan/p/3632525.html. ?(? ? ??)我是看这篇博客才入门的. 代码: 1 #include <cstdio> 2 #includ