网络流算法

标号法过程为:
(1) 先将 flag、 prev 和 alpha 这 3 个数组各元素都初始化-1 。
(2) 将源点初始化为已标号未检查顶点,即 flag[0] = 0, prev[0] = 0, alpha[0] = INF, INF 表示无穷大;并将源点入队列。
(3) 当队列非空并且汇点没有标号,从队列头取出队列头顶点,设这个顶点为 v, v 肯定是已标号未检查顶点;因此,检查顶点 v 的正向和反向“邻接”顶点,如果没有标号并当前可以进行标号,则对这些顶点进行标号并入队列,这些顶点都是已标号未检查顶点;此后顶点 v 为已标号已检查顶点。反复执行这一步直至队列为空或汇点已获得标

测试数据:(6 表示顶点数, 10表示边数!)

6 10  
0 1 8 2
0 2 4 3
1 3 2 2
1 4 2 2
2 1 4 2
2 3 1 1
2 4 4 0
3 4 6 0
3 5 9 3
4 5 7 2

  1 //////// 标号法求网络最大流.
  2
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <cmath>
  6
  7 #define _clr(x, y) memset(x, y, sizeof(x))
  8 #define Min(x, y) (x < y ? x : y)
  9 #define INF 0x3f3f3f3f
 10 #define N 1005
 11 using namespace std;
 12
 13 struct ArcNode // 弧结构:c表示容量,f表示流量.
 14 {
 15     int c, f;
 16 };
 17 ArcNode edge[N][N];
 18 int queue[N]; // 队列
 19 int flag[N]; // -1表示未检查未访问,0表示已访问未检查相邻顶点,1表示已访问已检查相邻顶点
 20 int pre[N]; // 保存一个点的前驱.
 21 int alpha[N]; //保存一个点的可改进量
 22 int n;
 23
 24 int abs(int a)
 25 {
 26     return a < 0 ? -a : a;
 27 }
 28
 29 void ford()
 30 {
 31     while(1)
 32     {
 33         //  初始化,
 34         int front=0, rear=0;
 35         _clr(flag, -1);
 36         _clr(pre, -1);
 37         _clr(alpha, -1);
 38         flag[0] = 0, pre[0] = 0, alpha[0] = INF;
 39         queue[rear++] = 0; // 把源点加入队列
 40         while(front<rear && flag[n-1]==-1) // 队列非空 且 汇点还未标号
 41         {
 42             int v = queue[front++];
 43             for(int i=0; i<n; i++)  // 检查顶点v的相邻顶点
 44             {
 45                 if(flag[i]==-1)  // i点还未访问
 46                 {
 47                     if(edge[v][i].c<INF && edge[v][i].f<edge[v][i].c) // 正向且流量未满
 48                     {
 49                         flag[i] = 0, pre[i] = v;
 50                         alpha[i] = Min(alpha[v], edge[v][i].c-edge[v][i].f);
 51                         queue[rear++] = i;
 52                     }
 53                     else if(edge[i][v].c<INF && edge[i][v].f)  // 反向 且 有流量
 54                     {
 55                         flag[i] = 0, pre[i] = -v;
 56                         alpha[i] = Min(alpha[v], edge[i][v].f);
 57                         queue[rear++] = i;
 58                     }
 59                 }
 60             }
 61             flag[v] = 1;  // 加上源点流出量即是 最大流!
 62         }
 63
 64         if(flag[n-1]==-1 || alpha[n-1]==0) break; // 汇点无法标号 或 得到的可改进量为0:即没有可改进路.
 65
 66         // 进行调整后得到残留网络.
 67         int k1=n-1, k2=abs(pre[k1]);
 68         int a = alpha[n-1];
 69         while(1)
 70         {
 71             if(edge[k2][k1].f<INF)  // 正向加上可改进量
 72                 edge[k2][k1].f += a;
 73             else  // 反向减去可改进量
 74                 edge[k1][k2].f -= a;
 75             if(k2==0) break; // 直至到源点.
 76             k1 = k2, k2 = abs(pre[k1]);
 77         }
 78     }
 79
 80     int MaxFlow=0;
 81     for(int i=0; i<n; i++)
 82         for(int j=0; j<n; j++)
 83             if(edge[i][j].f<INF)
 84             {
 85                 printf("%d->%d: %d\n", i,j,edge[i][j].f);  // 输出各条弧的实际流量
 86                 if(i==0)
 87                     MaxFlow += edge[i][j].f;  // 加上源点流出量即是 最大流!
 88             }
 89     printf("MaxFlow: %d\n", MaxFlow);
 90 }
 91 int main()
 92 {
 93     int m, a, b, c, f;
 94     while(~scanf("%d%d", &n, &m))
 95     {
 96         for(int i=0; i<n; i++)
 97             for(int j=0; j<n; j++)
 98                 edge[i][j].c=edge[i][j].f = INF;
 99         while(m--)
100         {
101             scanf("%d%d%d%d", &a, &b, &c, &f);
102             edge[a][b].c = c, edge[a][b].f = f;
103         }
104     puts("before test");
105     ford();
106     puts("after test");
107     }
108     return 0;
109 }

时间: 2024-10-10 08:08:19

网络流算法的相关文章

网络流算法Dinic的Python实现

在上一篇我们提到了网络流算法Push-relabel,那是90年代提出的算法,算是比较新的,而现在要说的Dinic算法则是由以色列人Dinitz在冷战时期,即60-70年代提出的算法变种而来的,其算法复杂度为O(mn^2). Dinic算法主要思想也是基于FF算法的,改进的地方也是减少寻找增广路径的迭代次数.此处Dinitz大师引用了一个非常聪明的数据结构,Layer Network,分层网络,该结构是由BFS tree启发得到的,它跟BFS tree的区别在于,BFS tree只保存到每一层的

网络流算法--Ford-Fulkerson方法及其多种实现

原文链接:http://www.cnblogs.com/luweiseu/archive/2012/07/14/2591573.html 7. 网络流算法--Ford-Fulkerson方法及其多种实现 网络流 在上一章中我们讨论的主题是图中顶点之间的最短路径,例如公路地图上两地点之间的最短路径,所以我们将公路地图抽象为有向带权图.本章我们将对基于有向带权图的模型做进一步扩展. 很多系统中涉及流量问题,例如公路系统中车流量,网络中的数据信息流,供油管道的油流量等.我们可以将有向图进一步理解为"流

网络流算法模板

通过USACO草地排水学习了一下网络流,终于写好了几个模板. 最大流 BFS求增广路径 简述:通过BFS在网络中找出一条最短增广路径并修改流量(前向弧加可改进量X,后向弧则减去X),当不存在增广路径时得出最大流,时间效率O(nm^2). { ID: qty1272 PROG: ditch LANG: PASCAL } program ditch; var c,f:array[0..200,0..200]of longint; path,u:array[0..200]of longint; n,i

[转] 网络流算法--Ford-Fulkerson方法及其多种实现

网络流 转载自:http://www.cnblogs.com/luweiseu/archive/2012/07/14/2591573.html 在上一章中我们讨论的主题是图中顶点之间的最短路径,例如公路地图上两地点之间的最短路径,所以我们将公路地图抽象为有向带权图.本章我们将对基于有向带权图的模型做进一步扩展. 很多系统中涉及流量问题,例如公路系统中车流量,网络中的数据信息流,供油管道的油流量等.我们可以将有向图进一步理解为“流网络”(flow network),并利用这样的抽象模型求解有关流量

网络流算法Push-relabel的Python实现

网络流的背景我就不多说了,就是在一个有向图中找出最大的流量,有意思的是,该问题的对偶问题为最小割,找到一种切分,使得图的两边的流通量最小,而且通常对偶问题是原问题的一个下界,但最小割正好等于最大流,即切割的边就是最大流中各个path饱和边的一个组合.说得可能比较含糊,这里想要了解清楚还是查阅相关资料吧. 最大流最原始最经典的解法就是FF算法,算法复杂度为O(mC),C为边的容量的总和,m为边数.而今天讲的Push-relabel算法是90年代提出的高效算法,复杂度为O(n^3),其实网络流最关键

关于网络流算法(2)

了解最大流解法: 网络流的相关基础知识很容易获得,详细的有<算导>,简单的有刘汝佳<算法竞赛入门>,这里选用的也是刘的书从Page207开始的内容. 这里要补充一些值得注意的基础: 最大流问题中的三个约束条件:容量限制条件.斜对成性条件.流量平衡条件: 网络流问题中边(Edge)的有向性. 1.1 BFS算法 因为<算法竞赛入门>中的E-K算法是基于BFS遍历方法的,说是很容易找到让DFS很慢的例子所以改为BFS,自己又已经把以前看的书全部忘记了,无奈只能开这个1.1,

ISAP网络流算法

ISAP全称Improved Shortest Augmenting Path,意指在SAP算法进行优化.SAP即Edmonds-Karp算法,其具体思路是通过不断向残存网络推送流量来计算整个网络的最大流.阅读本文要求掌握网络流的基础概念,不懂的出门左拐算法导论.ISAP的时间复杂度与EK算法一致,而EK算法的时间复杂度为min(O(E|f|),O(VE^2)),其中O(E|f|)部分是因为其是在FORD-FULKERSON算法上的改进.EK算法在FF算法的基础上将随意取增广路径替换为取最短增广

关于网络流算法(3)

实现MCMF的基础上进行尝试针对题目修改代码就方便许多,这里的一个难点是如何输出MCMF对应的各条流路径(网络路径).实现了MCMF之后很长的一段时间我一直在走弯路,最后发现是自己的测试数据并不方便手算而且一开始采用的模板本身有错误,另一方面因为我之前并没有接触过图论算法,对这些现学的算法实现和运行细节不熟悉.在调整心态之后我决定使用自己设计的图作为调试用例并慢节奏地调试理解,稳扎稳打. 这里有一个博客,作者的思路与我一致,其内容对我有很大帮助. 2.1 多服务器(固定)-多消费结点.无输出的版

图论专题小结:网络流算法之ISAP算法

ISAP算法 ISAP(Improved Shortest Augument Path)算法是改进版的SAP算法,如果对效率要求很高的时候,可以用该算法. (1)概述:算法基于这样的一个事实:每次增广之后,任意结点到汇点(在残余网络中)的最短距离都不会减小.这样,我们可以利用d[i[表示结点i到汇点的距离的下界.然后再增广过程当中不断地修改这个下界.增广的时候和Dinic算法类似,只允许沿着d[i]==d[j]+1的弧(i,j)走. 不难证明,d[i[满足两个条件:(1)d[t]=0;(2)对任

网络流算法与建模总结

[算法] 1.最大流 (1) 容量限制:对于∀u,v∈V ,要求 f (u,v) ≤ c(u,v). (2) 反对称性:对于∀u,v∈V ,要求 f (u,v) = − f (v,u). (3) 流量平衡:对于∀u∈V −{s,t},要求∑f(u,v)=0. dinic 根据残量网络计算层次图. 在层次图中使用DFS沿阻塞流(不考虑反向弧时的极大流 层次图中的)进行增广直到不存在增广路 重复以上步骤直到无法增广 int cur[N]; int vis[N],d[N],q[N],head,tail