#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. ADO.NET之一:连接层

    ADO.NET大部分由System.Data.dll核心程序集来表示. ADO.NET类库有三种完全不听的方式来实现数据访问:连接式.断开式和通过Entity框架.连接式就是会一直占用网络资源,断开式 ...

  2. js字符串内容包含单引号‘’和双引号“”怎么办?

    如果javascript中的字符串包含单引号和双引号,可以用转义字符来标识 'I\'m \"OK\"!'; 表示的字符串内容是:I'm "OK"! 转义字符\可 ...

  3. v-if

    vue中通过v-if,v-else-if,v-else的对应的Boolean值来操作元素在dom中是否移除. 这里就以单纯的true,false来模拟一下.注:标签属性去出来的值为string类型. ...

  4. js一键复制到剪切板

    <div id='demo'>我就是被复制的内容<span>点击复制<span></div> $('#demo').on('click','span', ...

  5. 【学时总结】 ◆学时·IV◆ 数位DP

    [学时·IV] 数位DP ■基本策略■ 说白了就是超时和不超时的区别 :) 有一些特别的题与数位有关,但是用一般的枚举算法会超时.这时候就有人提出了--我们可以用动态规划!通过数字前一位和后一位之间的 ...

  6. VS2013使用自带的数据库 Microsoft SQL Server 2012 Express LocalDB

    注:DeptLocalDB:自己取的数据库实例名称 DeptSharedLocalDB:自己取的实例共享名称np:\\.\pipe\LOCALDB#SH7C6ED5\tsql\query:命名管道名称 ...

  7. Tomcat+jdk 环境处理 java jsp代码编写web环境的容器

    Tomcat是由 Apache 软件基金会下属的 Jakarta 项目开发的一个Servlet 容器,按照 SunMicrosystems 提供的技术规范,实现了对 Servlet 和 JavaSer ...

  8. oauth2.0协议接口-第一篇-api逻辑

    开放平台是支持OAuth2.0和RESTful协议的资源分享平台,经过授权的合作伙伴可以读取和写入资讯.用户.文件.数据库等资源. 1.创建数据库表结构 CMSSyncClient(数据同步客户端) ...

  9. [BZOJ1899]Lunch 午餐(DP)

    [BZOJ1899] 首先有个很贪心的思路,吃饭时间长的最先打饭为最优,所以开始先排个序 然后考虑DP,我们不需要知道某个人在哪个对,只要关注总的时间就行了 肯定需要一维表示当前同学编号,还需要表示某 ...

  10. Android面试收集录 Android布局

    1.请说出Android中的五种布局,并介绍作用? FrameLayout(堆栈布局),层叠方式显示,类似于PhotoShop上的层叠图层. LinearLayout(线性布局),将视图以水平或者垂直 ...