zoukankan      html  css  js  c++  java
  • 最大流(一)—— Edmond-Karp算法

    EK算法为最短增广路算法,具体步骤:

    1)初始化网络中所有边的容量 c < u , v > 为该边的容量,同时反向边 c < v , u > 为0,初始化最大流为0。

    2)在残留网络中找一条从源S到汇T的增广路p。如果能找到,转步骤(3);如果不能找到,则转步骤(5)。

    3)在增广路p中找到所谓的“瓶颈”边,即路径中的最小边,记录下这个值X,并且累加进最大流。

    4)将增广路中所有的 c < u ,v > 减去X,所有 c < v , u > 加上X,构成新的残留网络。转步骤(2)。

    5)得到网络的最大流,退出。

    在点数较少时比较有利

    时间复杂度:O(n*m^2)

    空间复杂度:O(n^2)

    EK算法代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=110;     ///最大点个数
    const int inf=0x7fffffff;
    int mp[maxn][maxn],n,p[maxn];
    bool vis[maxn];
    ///mp:邻接矩阵
    ///p:点的前驱
    ///vis:找增广路时用于避免增广点的重复选取
    bool EK_Bfs(int st,int ed) {
        queue<int>que;
        for(int i=0;i<=n;i++) p[i]=-1,vis[i]=false;  ///初始化
        que.push(st);
        vis[st]=true;
        while(!que.empty()) {
            int e=que.front();
            if(e==ed) return true;  ///到达ed点,说明增广路已经找到
            que.pop();
            for(int i=1;i<=n;i++) {
                if(mp[e][i]&&!vis[i]) {    ///如果当前边有流且增广点未标记
                    vis[i]=true;
                    p[i]=e;        ///记录增广点前驱点
                    que.push(i);
    
                }
            }
        }
        return false;       ///找不到增广路
    }
    int EK_Max_Flow(int st,int ed) {
        int max_flow=0;     ///最大流量
        while(EK_Bfs(st,ed)) {  ///只要能找到从st到ed的增广路,就继续循环
            int minn=inf;
            int u=ed;
            while(p[u]!=-1) {       ///找出增广路中的“瓶颈”边
                minn=min(mp[p[u]][u],minn);
                u=p[u];
            }
            max_flow+=minn;     ///累加进最大流
            u=ed;
            while(p[u]!=-1) {   ///修改路径上的边容量
                mp[p[u]][u]-=minn;
                mp[u][p[u]]+=minn;
                u=p[u];
            }
        }
        return max_flow;
    }
    int main()
    {
        int m,st,ed;      ///m:边数目  st:起点  ed:终点
        cin>>n>>m;          ///因为懒得打所以用c++的输入输出流,提交代码不建议使用
        cin>>st>>ed;
        for(int i=1;i<=m;i++) {
            int u,v,w;
            cin>>u>>v>>w;
            mp[u][v]+=w;     ///建立u到v的权值为w的边
            mp[v][u]=0;     ///可写可不写,写上为了更好的理解
        }
        cout<<EK_Max_Flow(st,ed)<<endl;
        return 0;
    }
    ///时间复杂度:O(n*m^2)
    ///空间复杂度:O(n^2)
    

      

  • 相关阅读:
    vue中使用第三方UI库的移动端rem适配方案
    前端规范--eslint standard
    从上往下打印二叉树
    栈的压入,弹出序列
    随机森林
    LR
    顺时针打印矩阵
    包含min函数的栈
    树的子结构
    合并两个有序链表
  • 原文地址:https://www.cnblogs.com/wuliking/p/11199760.html
Copyright © 2011-2022 走看看