最大流之sap算法

若有向图G = (V , E)满足下列条件:

1、有且仅有一个顶点S,它的入度为 0 ,这个顶点称为源点。

2、有且仅有一个顶点T,它的出度为 0 ,这个顶点称为汇点。

3、每一条弧都有一个非负数,叫做这条边的容量,边(Vi , Vj)的容量用 Cij 来表示。

则此有向图称为网络流图,记为 G = ( V , E , C) ;

对于网络流图G中,每一条弧( i , j )都给定一个非负数Fij,对于一组数据满足下面三个条件时,称为可行流;

1、对于每条弧都有 Fij < Cij ;

2、出了源点S和汇点T之外,中间任意点流量守恒,即输入流等于输出流;

3、对于源点S和汇点T,从S出去多少就会从T流入多少;

假如有这么一条路,从源点开始,一直一段一段的连到了汇点,并且这条路上的每一段满足Fij < Cij ,则称这条路为增广路;

当找不到增广路时,当前流量就是最大流。

寻找增广路时可以简单地从源点开始做bfs,并不断修改这条路上的最大流。

但事实上并不是这么简单,上面所说的增广路还不是很完整,中间还存在一些细节问题,例如:

我们通过bfs遍历后得到第一条增广路 1 - 2 - 3 - 4 ,然后就不存在增广路径了,其实并不是这样,这个网络流的最大流明显为 2
,我们可以是使用一个叫反向边的概念来解决这个问题,如图:

这样就解决了增广路算法中的一些细节问题;

加入一个网络图中有4个点,5条边组成。如下:

5 4

1 2 40

1 4 20

2 4 20

2 3 30

3 4 10

求最大流是多少?

下面给出相应的代码:

?





1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

#include<iostream>

#include<queue>

using
namespace std ;

int n , m ;

int map[210][210] ;

int
path[210] ;

int
flow[210] ;

int
bfs()   {

    queue<int> q ;

    memset(path,-1,sizeof(path)) ;

    path[1] = 0 ;

    flow[1] = (1<<30) ;

    q.push(1) ;

    while(!q.empty())   {

        int
t = q.front() ;

        q.pop() ;

        if(t == m) break
;

        for(int
i = 2 ; i <= m ; i++)

            if(path[i] == -1 && map[t][i])  {      // 该路径没有被访问过

                flow[i]=flow[t]<map[t][i]?flow[t]:map[t][i];   // 该路径最小流量

                q.push(i) ;

                path[i] = t ;   // 存储路径

            }

    }

    if(path[m] == -1)

        return
-1 ;

    return
flow[m] ;

}

void
Edmonds_Karp() {

    int
max_flow = 0 , floww ;

     while((floww=bfs())!=-1)   {

        max_flow += floww ;

        int
s , t ;

        t = m ;

        while(t != 1 )  {

            s = path[t] ;

            map[s][t] -= floww ;

            map[t][s] += floww ;

            t = s ;

        }

    }

    cout << max_flow << endl ;

}

int
main()  {

    while(cin >> n >> m)    {

        memset(map,0,sizeof(map)) ;

        while(n--) {

            int
u , v , cost ;

            cin >> u >> v >> cost ;

            map[u][v] += cost ;

        }

        Edmonds_Karp() ;

    }

    return
0 ;

}

  

最大流之sap算法,码迷,mamicode.com

时间: 2024-12-15 04:23:42

最大流之sap算法的相关文章

hdu3572Task Schedule 最大流,判断满流 优化的SAP算法

PS:多校联赛的题目质量还是挺高的.建图不会啊,看了题解才会的. 参考博客:http://blog.csdn.net/luyuncheng/article/details/7944417 看了上面博客里的题解,思路就有了.不过建图还是有点麻烦.我把源点设为n+1 (不想从0开始,不修改模版),汇点就是n+2+MAX,其中MAX是题目中Ei的最大值. 这题,我有疑问:优化过的SAP算法的时间复杂度是O(m*n^2),此题的n最大为1000,m为50万,时间超过5亿了.1s的时限居然过了. 其中有个

最大流(二)—— SAP算法

直接上代码 #include<vector> #include<cstdio> #include<iostream> #include<cmath> #include<queue> #define numm ch-48 #define pd putchar(' ') #define pn putchar('\n') #define pb push_back #define fi first #define se second #define fr

sap 算法心得

2014 11 13 今天接触了sap算法,感觉收获很多,写一些心得. 上网查sap,“设点i的标号为D[i],那么如果将满足D[i]=D[j]+1的弧(i,j)叫做允许弧,且增广时只走允许弧,那么就可以达到“怎么走都是最短路”的效果”.其实就是dinic 分层次的思想,d[i]即为当前点到汇点的距离,d数组给所有点分层.(如果不清楚自行查找) 维护距离标号的方法:当找增广路过程中发现某点出发没有允许弧时,将这个点的距离标号设为由它出发的所有弧的终点的距离标号的最小值加一.这种维护距离标号的方法

最大流 Dinic + Sap 模板

不说别的,直接上模板. Dinic+当前弧优化: struct Edge{ int x,y,c,ne; }e[M*2]; int be[N],all; int d[N],q[N]; int stack[N],top;//栈存的是边 int cur[N];//当前弧优化 void add(int x, int y, int z)//需保证相反边第一个为偶数 { e[all].x=x; e[all].y=y; e[all].c=z; e[all].ne=be[x]; be[x]=all++; e[a

网络流(三)----最大流SAP算法

以  HDU 3572  Task Schedule 为例的模板 Code: #include <cstdio> #include <cstdlib> #include <cstring> #include <cctype> #include <cmath> #include <algorithm> #include <vector> #include <queue> #include <stack>

hdu2883 最大流,判断满流 优化的SAP算法

这是09年的多校联赛题目,比10年的难度要大.如果没做过hdu3572,建议先去做.有了解题思维再来做这题. 这题与hdu3572类似.但是1 <= si < ei <= 1,000,000的限制使得我们如果像HDU3572那样建图,会使得边的数量太多.从而超时. 看看别人的题解 http://www.cnblogs.com/wally/archive/2013/05/03/3057066.html  离散化的思想 #include<iostream> #include<

最大流 SAP 算法伪代码

代码当中是以边的方式存图,邻接矩阵类似. 1 int dfs(int u, int flow) 2 { 3 int tmp, out = 0; 4 for (int p = fst[u]; p; p = nxt[p]) { 5 if (w[p] <= 0 || dis[u] != dis[v[p]] + 1) 6 continue; 7 w[p] -= tmp = dfs(v[p], min(flow - out, w[p])); 8 w[p + 1] += tmp; 9 if ((out +=

关于最大流的EdmondsKarp算法详解

最近大三学生让我去讲课,我就恶补了最大流算法,笔者认为最重要的是让学弟学妹们入门,知道算法怎么来的?为什么是这样?理解的话提出自己的改进,然后再看看Dinic.SAP和ISAP算法….. 一.概念引入 首先要先清楚最大流的含义,就是说从源点到经过的所有路径的最终到达汇点的所有流量和. 流网络G=(V,E)是一个有向图,其中每条边(u,v)∈E均有一个非负容量c(u,v)>=0.如果(u,v)不属于E,则假定c(u,v)=0.流网络中有两个特别的顶点:源点s和汇点t.下图展示了一个流网络的实例(其

HDU 3549 Flow Problem (用一道最裸的最大流开启网络流算法之路)

Flow Problem Time Limit: 5000/5000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) Total Submission(s): 9423    Accepted Submission(s): 4405 Problem Description Network flow is a well-known difficult problem for ACMers. Given a graph, y