#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int dp[][],pre[];
const int tmin=;
int maxflow;
void EK(int start,int end,int n){
while(){
queue<int>q;
q.push();//源点为1,进队
int minflow=tmin;
memset(pre,,sizeof(pre));//初始化增广路径数组,题目中的顶点是从1开始的
while(!q.empty()){//bfs找增广路
int u=q.front();
q.pop();
for(int i=;i<=n;i++){
if(dp[u][i]>&&!pre[i]){//pre[i]除了记录当前顶点的父亲,还记录当前顶点有没被访问过
pre[i]=u;
q.push(i);
}
}
}
if(pre[end]==)//顶点的父亲为空,表示找不到增广路,很容易理解吧。。
break;
for(int i=end;i!=start;i=pre[i]){//找出增广路中最小残余量
minflow=min(dp[pre[i]][i],minflow);
}
for(int i=end;i!=start;i=pre[i]){//更新增广路中正反向弧的流量
dp[pre[i]][i]-=minflow;
dp[i][pre[i]]+=minflow;
}
maxflow+=minflow;
}
}
int main(){
int count=;
int n,m;
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
memset(dp,,sizeof(dp));
memset(pre,,sizeof(pre));
count++;
int u,v,w;
for(int i=;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
dp[u][v]+=w;
}
maxflow=;
EK(,n,n);
printf("Case %d: %d\n",count,maxflow);
}
return ;
}

EdmondsKarp算法,简称EK算法,O(m^2n)

因为是初学教程,所以我会尽量避免繁杂的数学公式和证明。也尽量给出了较为完整的代码。 
本文的目标群体是网络流的初学者,尤其是看了各种NB的教程也没看懂怎么求最大流的小盆友们。本文的目的是,解释基本的网络流模型,最基础的最大流求法,即bfs找增广路法,也就是EK法,全名是Edmond-Karp,其实我倒是觉得记一下算法的全名和来历可以不时的拿出来装一装。 
    比如说这个,EK算法首先由俄罗斯科学家Dinic在1970年提出,没错,就是dinic算法的创始人,实际上他提出的也正是dinic算法,在EK的基础上加入了层次优化,这个我们以后再说,1972年Jack Edmonds和Richard Karp发表了没有层次优化的EK算法。但实际上他们是比1790年更早的时候就独立弄出来了。 
    你看,研究一下历史也是很有趣的。 
    扯远了,首先来看一下基本的网络流最大流模型。 
    有n个点,有m条有向边,有一个点很特殊,只出不进,叫做源点,通常规定为1号点。另一个点也很特殊,只进不出,叫做汇点,通常规定为n号点。每条有向边上有两个量,容量和流量,从i到j的容量通常用c[I,j]表示,流量则通常是f[I,j]。通常可以把这些边想象成道路,流量就是这条道路的车流量,容量就是道路可承受的最大的车流量。很显然的,流量<=容量。而对于每个不是源点和汇点的点来说,可以类比的想象成没有存储功能的货物的中转站,所有”进入”他们的流量和等于所有从他本身”出去”的流量。 
    把源点比作工厂的话,问题就是求从工厂最大可以发出多少货物,是不至于超过道路的容量限制,也就是,最大流。 
    比如这个图。每条边旁边的数字表示它的容量。 
    

下面我们来考虑如何求最大流。

首先,假如所有边上的流量都没有超过容量(不大于容量),那么就把这一组流量,或者说,这个流,称为一个可行流。一个最简单的例子就是,零流,即所有的流量都是0的流。 
我们就从这个零流开始考虑,假如有这么一条路,这条路从源点开始一直一段一段的连到了汇点,并且,这条路上的每一段都满足流量<容量,注意,是严格的<,而不是<=。那么,我们一定能找到这条路上的每一段的(容量-流量)的值当中的最小值delta。我们把这条路上每一段的流量都加上这个delta,一定可以保证这个流依然是可行流,这是显然的。 
    这样我们就得到了一个更大的流,他的流量是之前的流量+delta,而这条路就叫做增广路。 
    我们不断地从起点开始寻找增广路,每次都对其进行增广,直到源点和汇点不连通,也就是找不到增广路为止。当找不到增广路的时候,当前的流量就是最大流,这个结论非常重要。 
寻找增广路的时候我们可以简单的从源点开始做bfs,并不断修改这条路上的delta量,直到找到源点或者找不到增广路。 
这里要先补充一点,在程序实现的时候,我们通常只是用一个c数组来记录容量,而不记录流量,当流量+1的时候,我们可以通过容量-1来实现,以方便程序的实现。

EK算法模板的更多相关文章

  1. 最大流的EK算法模板

    模板题:洛谷p3376 题目大意: 给出一个网络图,以及其源点和汇点,求出其网络最大流. 基本思路: 套模板 EK的时间复杂度O(V*E^2) EK算法思路: 1.通过BFS拓展合法节点(每个节点在本 ...

  2. 网络流EK算法模板

    \(EK\)算法的思想就是每一次找一条增广路进行增广. 注意几个点: 存图时\(head\)数组要设为\(-1\). 存图的代码是这样的: inline void add(int u, int v, ...

  3. 最大流EK算法模板

    最近学了下最大流算法,大概思想算是懵懵懂懂了,现在想把模板记录下来,以备后面深刻学习之用. #include<cstdio> #include<cstring> using n ...

  4. POJ 1273 - Drainage Ditches - [最大流模板题] - [EK算法模板][Dinic算法模板 - 邻接表型]

    题目链接:http://poj.org/problem?id=1273 Time Limit: 1000MS Memory Limit: 10000K Description Every time i ...

  5. HDU-1532 Drainage Ditches (最大流,EK算法模板)

    题目大意:最大流的模板题...源点是0,汇点是n-1. 代码如下: # include<iostream> # include<cstdio> # include<cma ...

  6. 网络流 EK算法模板。

    这篇博客讲得很好 #include<queue> #include<stdio.h> #include<string.h> using namespace std; ...

  7. Drainage Ditches(网络流(EK算法))

    计算最大流,EK算法模板题. #include <stdio.h> #include <string.h> #include <queue> using names ...

  8. ACM - 图论- 网络流 - 算法模板

    \(EK\) 算法模板 #include <iostream> #include <queue> #include<string.h> using namespac ...

  9. ACM/ICPC 之 网络流入门-EK算法(参考模板)(POJ1273)

    基于残留网络与FF算法的改进-EK算法,核心是将一条边的单向残留容量的减少看做反向残留流量的增加. //网络流 //EK算法 //Time:16Ms Memory:348K #include<i ...

随机推荐

  1. 使用jdk进行数据迁移(sqlite迁移mysql)

    直接粘贴代码 注意:rewriteBatchedStatements=true(加快连接速度) package com.wbg; import org.omg.Messaging.SYNC_WITH_ ...

  2. hadoop中使用的Unsafe.java

    今天查看hadoop源代码, 发现有个Unsafe.java 稍微总结下 优势 1 减少线程调度开销, Unsafe.java 通过采用非堵塞原子方式来减少线程调度开销        2 传统线程通信 ...

  3. 居中未知元素(翻译https://css-tricks.com/centering-in-the-unknown/)

    在web开发中,当你遇到居中元素时,知道越多关于元素本身和父级元素的信息,居中做起来就很轻松.但是,当遇到你一点都不知道的元素该怎么办? It's still kinda doable. 不会很难:已 ...

  4. WPF与Silverlight对比

    1.WPF中控件的肤色可以直接:telerik:StyleManager.Theme=”XXXXX”,不用再导入肤色的dll包.可Silverlight使用系统肤色时,要导入肤色的dll包. WPF引 ...

  5. avalon.js的循环操作在表格中的应用

    avalon.js的循环操作在表格中的应用 一个JAVA开发,因为做的门户系统中,数据的展示加载的速度很影响使用效果,想到的是尽量少的请求后台,然后接触到了avalon,看介绍这是一个很轻很轻的MVV ...

  6. 【A* 网络流】codechef Chef and Cut

    高嘉煊讲的杂题:A*和网络流的练手题 题目大意 https://s3.amazonaws.com/codechef_shared/download/translated/SEPT16/mandarin ...

  7. Smartforms 设置纸张打印格式

    在sap做一个打印报表,要先设置一个纸张打印格式,下面以工厂中常用来打印的针孔纸为例,在sap设置该纸张的打印格式,以用于报表: 1.运行事务代码SPAD:选择工具栏上的[完全管理]按钮——>选 ...

  8. Integer和int使用==比较的总结

    public static void main(String[] args) { int i1 = 128; Integer i2 = 128; Integer i3 = new Integer(12 ...

  9. spring-传统AOP

    Spring传统AOP AOP的增强类型 AOP联盟定义了Advice(org.aopalliance.aop.Interface.Advice) 五类(目标类方法的连接点): 1.  前置通知(or ...

  10. spring cloud 学习之服务消费者(rest+ribbon)

    学习自 http://blog.csdn.net/forezp/article/details/81040946 方志朋的博客 在微服务架构中,业务都会被拆分成一个独立的服务,服务与服务的通讯是基于h ...