zoukankan      html  css  js  c++  java
  • 最大流的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;
    }
  • 相关阅读:
    前端工程化浅学
    jQuery学习
    黄金票据和白银票据获取域控权限
    [转]0day零距离
    [转]走近0day
    [转]人生如解 -- 关于破解组织的乱弹
    [转]WAREZ无形帝国
    [转]BSD系统正在死亡?一些安全研究人员这样认为
    Solaris:你好奇的十件事
    Windows和Office激活汇总
  • 原文地址:https://www.cnblogs.com/imzscilovecode/p/8724078.html
Copyright © 2011-2022 走看看