SCL--最大流
2015-04-08 17:52:08
最大流小结:
最大流的算法学了已经有一段时间了,题目也做了一些。是时候总结一个经常用的模板了。
(1)首先是最常用的Dinic算法:
相比于EK(bfs找增广路)、FF(dfs找增广路),dinic算法每次总是寻找最短的增广路,因为在最短增广路的长度在增广过程中始终不会变短.换言之:在dinic的分层图中终点只会变远。所以无需每次都用过 bfs / dfs 来盲目地找增广路,我们可以预先地进行一次 bfs ,将图划成一个分层图,然后在上面尽量地找增广路,直到在该分层图中找不到了(说明最短增广路的长度变长)则再重新构建分层图,如此循环直到构不成分层图。
复杂度计算:每次构建分层图的复杂度为 O(E),由于每一步 bfs 构建分层图至少使得最短增广路长度增加 1,增广路最长为 V,所以最多构建 O(V) 次。dfs 找增广路的过程如果用当前弧优化,复杂度为 O(E * V)。
所以总的复杂度:O(V * (E + E * V)) --> O(E * V^2)
1 const int MAXN = 210; 2 const int MAXM = 410; 3 4 struct edge{ 5 int v,next,c; 6 }; 7 8 struct Max_flow{ 9 int st,ed,lev[MAXN],first[MAXN],now[MAXN],ecnt; 10 edge e[MAXM]; 11 void init(int a,int b){ 12 st = a,ed = b; 13 MEM(first,-1); 14 ecnt = 0; 15 } 16 void add_edge(int u,int v,int c){ 17 e[ecnt].next = first[u]; 18 e[ecnt].v = v; 19 e[ecnt].c = c; 20 first[u] = ecnt++; 21 22 e[ecnt].next = first[v]; 23 e[ecnt].v = u; 24 e[ecnt].c = 0; 25 first[v] = ecnt++; 26 } 27 bool bfs(){ 28 queue<int> Q; 29 while(!Q.empty()) Q.pop(); 30 Q.push(st); 31 MEM(lev,-1); 32 lev[st] = 0; 33 while(!Q.empty()){ 34 int x = Q.front(); Q.pop(); 35 for(int i = first[x]; ~i; i = e[i].next){ 36 int v = e[i].v; 37 if(lev[v] < 0 && e[i].c > 0){ 38 lev[v] = lev[x] + 1; 39 Q.push(v); 40 } 41 } 42 } 43 return lev[ed] != -1; 44 } 45 int dfs(int p,int minf){ 46 if(p == ed || minf == 0) return minf; 47 for(int &i = now[p]; ~i; i = e[i].next){ 48 int v = e[i].v; 49 if(lev[v] == lev[p] + 1 && e[i].c > 0){ 50 int d = dfs(v,min(e[i].c,minf)); 51 if(d > 0){ 52 e[i].c -= d; 53 e[i ^ 1].c += d; 54 return d; 55 } 56 } 57 } 58 return 0; 59 } 60 int dinic(){ 61 int max_flow = 0,pl; 62 while(bfs()){ 63 memcpy(now,first,sizeof(first)); 64 while((pl = dfs(st,INF)) > 0) 65 max_flow += pl; 66 } 67 return max_flow; 68 } 69 }MF;