标号法过程为:
(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