首页 > 编程语言 > 详细

网络流算法

时间:2015-02-13 01:25:51      阅读:365      评论:0      收藏:0      [点我收藏+]

 

 

标号法过程为:
(1) 先将 flagprev alpha 3 个数组各元素都初始化-1
(2) 将源点初始化为已标号未检查顶点,即 flag[0] = 0, prev[0] = 0, alpha[0] = INFINF 示无穷大;并将源点入队列。
(3) 当队列非空并且汇点没有标号,从队列头取出队列头顶点,设这个顶点为 vv 肯定是已标号未检查顶点;因此,检查顶点 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 }
View Code

 

网络流算法

原文:http://www.cnblogs.com/khan724/p/4289485.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!