网络流:最大流之SAP算法
Posted st-lovaer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了网络流:最大流之SAP算法相关的知识,希望对你有一定的参考价值。
网络流主要解决三种问题:最大流、最小流和费用流。
最大流算法主要有三种:EK算法、Dinic算法、SAP算法。
本篇博客是关于SAP算法的。最坏的情况下,SAP算法将达到复杂度O(VE2)。
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <queue> 5 #include <cstring> 6 7 using namespace std; 8 const int INF = 0x3f3f3f3f; 9 const int maxn = 200 + 10; 10 const int maxm = 200 + 10; 11 12 int n,m; 13 int head[maxn];//链式前向星 14 int tot = 0; 15 16 struct edge 17 { 18 int to; 19 int c; 20 int next; 21 edge(int x = 0, int y = 0, int z = 0) : to(x), c(y), next(z) {} 22 }es[maxm*2];//记录边 注意是2倍 23 24 void add_edge(int u, int v, int c) 25 { 26 es[tot] = edge(v,c,head[u]); 27 head[u] = tot++; 28 } 29 30 31 int SAP(int s, int t) 32 { 33 int numh[maxn],h[maxn],ce[maxn],pre[maxn]; 34 //numh 记录gap优化的统计高度数量数组,h 距离标号数组,ce 当前弧,pre前驱数组 35 int f, ans = 0, u, temp, neck, i; //初始化最大流为0 36 memset(h,0,sizeof(h)); 37 memset(numh,0,sizeof(numh)); 38 memset(pre,-1,sizeof(pre)); 39 for(i = 1; i <= n; i++) ce[i] = head[i]; 40 numh[0] = n; 41 u = s; 42 while(h[s] < n) 43 { 44 //寻找增广路 45 if(u == t) 46 { 47 f = INF; 48 for(i = s; i != t; i = es[ce[i]].to) 49 { 50 if(f > es[ce[i]].c) 51 { 52 neck = i; 53 f = es[ce[i]].c; 54 } 55 } 56 for(i = s; i != t; i = es[ce[i]].to) 57 { 58 temp = ce[i]; 59 es[temp].c -= f; 60 es[temp^1].c += f; 61 } 62 ans += f; 63 u = neck; 64 } 65 66 //寻找可行弧 67 for(i = ce[u]; i != -1; i = es[i].next) 68 if(es[i].c && h[u] == h[es[i].to] + 1) break; 69 70 //寻找增广路 71 if(i != -1) 72 { 73 ce[u] = i; 74 pre[es[i].to] = u; 75 u = es[i].to; 76 } 77 else 78 { 79 if(!--numh[h[u]]) break; //gap optimization 80 ce[u] = head[u]; 81 for(temp = n, i = head[u]; i != -1; i = es[i].next) 82 if(es[i].c) temp = min(temp, h[es[i].to]); 83 84 h[u] = temp + 1; 85 ++numh[h[u]]; 86 if(u != s) u = pre[u];//重标号并且从当前点前驱重新增广 87 } 88 89 } 90 return ans; 91 } 92 93 int main() 94 { 95 while(~scanf("%d%d",&n,&m)) 96 { 97 tot = 0; 98 memset(head,-1,sizeof(head)); 99 int u,v,c; 100 for(int i = 0; i < m; i++) 101 { 102 scanf("%d%d%d",&u,&v,&c); 103 add_edge(u,v,c); 104 add_edge(v,u,0);//增加反向边 105 } 106 int ans = SAP(1,n); 107 printf("%d ",ans); 108 } 109 return 0; 110 }
以上是关于网络流:最大流之SAP算法的主要内容,如果未能解决你的问题,请参考以下文章