最大流的EK算法模板

模板题:洛谷p3376

题目大意:

给出一个网络图,以及其源点和汇点,求出其网络最大流。

基本思路:

套模板

EK的时间复杂度O(V*E^2)

EK算法思路: 
1.通过BFS拓展合法节点(每个节点在本次BFS中仅遍历一次),找到汇点,并记录每个节点的前面节点(pre)(若找不到增广路,算法结束) 
2.通过BFS的记录,从汇点回溯回源点,记录下每条弧流量的**最小值**minn, ans += minn(否则就会超出某条边的限制流量) 
3.将所有经过的边的流量减去minn,反向边加上minn 
4.重复上述步骤,直到找不到增广路,算法结束。

代码如下:

#include<iostream>
#include<string>
#include<queue>
#include<vector>
#include<stack>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>

using namespace std;

typedef long long ll;
const int inf = 0x3f3f3f3f;
const int maxn =10000+10;
int n,m,st,en;
struct Flow{
    int st,en,num;
}flow[200000+10];
vector<int>gra[maxn];
bool vis[maxn];
int pre[maxn];
bool bfs(){
    memset(vis,false,sizeof(vis));
    vis[st]=true;
    queue<int>q;
    q.push(st);
    while(!q.empty()){
        int qf=q.front();
        q.pop();
        int sz=gra[qf].size();
        for(int i=0;i<sz;i++){
            int id=gra[qf][i];
            int v=flow[id].en;
            if(flow[id].num>0&&!vis[v]){
                vis[v]=true;
                q.push(v);
                pre[v]=id;
                if(v==en){
                    return true;
                }
            }
        }
    }
    return false;
}
int EK(){
    int max_flow=0;
    while(bfs()){
        int _min=inf;
        for(int i=en;i!=st;i=flow[pre[i]].st){
            _min=min(_min,flow[pre[i]].num);
        }
        for(int i=en;i!=st;i=flow[pre[i]].st){
            flow[pre[i]].num-=_min;
            flow[pre[i]+m].num+=_min;
        }
        max_flow+=_min;
    }
    return max_flow;
}
int main(){
    scanf("%d%d%d%d",&n,&m,&st,&en);
    for(int i=0;i<m;i++){
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w);
        flow[i].st=u;
        flow[i].en=v;
        flow[i].num=w;
        flow[i+m].st=v;
        flow[i+m].en=u;
        flow[i+m].num=0;
        gra[u].push_back(i);
        gra[v].push_back(i+m);
    }
    printf("%d
",EK());
    return 0;
}
原文地址:https://www.cnblogs.com/imzscilovecode/p/8724078.html