算法学习之路|网络流之最大流

简介: 最大流可以看做是把一些东西从源点s送到汇点t,可以从其他的点中转,每条边最多只能输送一定的物品,求最多可以把多少东西从s送到t,这样的问题就是最大流问题。

最大流可以看做是把一些东西从源点s送到汇点t,可以从其他的点中转,每条边最多只能输送一定的物品,求最多可以把多少东西从s送到t,这样的问题就是最大流问题。

节点1为源点,节点5位汇点
每一条边上的数字即为这条边最多能输送的数量,也称为容量。(对于不存在的边,容量为0)
这个图能够求出的最大流为24。
这时,实际运送的物品量即为流量。
有些边的流量不一定等于容量,也就是还可以在这条路上再流多几个物品,这时,容量减去流量的值,即为残量
残量会单独构成网络,但不一定联通s和t,这样的网络称作残量网络。
那么,应该怎么求最大流呢?
这里介绍一个最基础的算法,增广路算法。
在图上,从s开始,任意取一条路来走,走到t,增加流量。重复这样的操作。但是很快,我们可以发现,这样的做法不一定是最优的做法。所以,我们要给它一个改进的机会。
在图上建立反向弧,将容量设置为0,当从节点u流向节点v时,反向弧的流量也相应等于这条弧的流量的相反数。
那么,通过搜索,每一次寻找一条路径,使得流向汇点的总流量增加,这个过程叫做增广,走过的路为增广路。
可以证明,通过这个过程,经过多次的增广,必然会陷入不能增广的情况,这时,流向汇点的总流量即为最大流。
只要残量网络中s和t是连通的,必然会得到一条增广路径。
找路径最简单的办法就是用DFS,但是对于一些具有刁钻数据的网络流题目,DFS可能会空间溢出或者超时,所以使用到BFS,也就是题目中说的Edmonds-Karp算法。
代码模板(来自算法竞赛入门第二版(刘汝佳)):

struct edge{
    int from,to,cap,flow;
    edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
struct Edmonds_Karp{
    int n,m;
    vector<edge>edges;//边数的两倍
    vector<int>g[maxn];//邻接表,g[i][j]表示节点i的第j条边在e数组中的序号
    int a[maxn];//当起点到i的可改进量
    int p[maxn];//最短路树上p的入弧编号
    void init(int n){
        for(int i=0;i<n;i++) g[i].clear();
        edges.clear();
    }
    void addedge(int from,int to,int cap){
        edges.push_back(edge(from,to,cap,0));
        edges.push_back(edge(to,from,0,0));//反向弧
        m=edges.size();
        g[from].push_back(m-2);
        g[to].push_back(m-1);
    }
    int Maxflow(int s,int t){
        int flow=0;
        for(;;){
            memset(a,0,sizeof(a));
            queue<int>q;
            q.push(s);
            a[s]=inf;
            while(!q.empty()){
                int x=q.front();q.pop();
                for(int i=0;i<(int)g[x].size();i++){
                    edge&e=edges[g[x][i]];
                    if(!a[e.to]&&e.cap>e.flow){
                        p[e.to]=g[x][i];
                        a[e.to]=min(a[x],e.cap-e.flow);
                        q.push(e.to);
                    }
                }
                if(a[t]) break;
            }
            if(!a[t]) break;
            for(int u=t;u!=s;u=edges[p[u]].from){
                edges[p[u]].flow+=a[t];
                edges[p[u]^1].flow-=a[t];
            }
            flow+=a[t];
        }
        return flow;
    }
}EK;
目录
相关文章
|
13天前
|
存储 算法 Windows
课程视频|R语言bnlearn包:贝叶斯网络的构造及参数学习的原理和实例(下)
课程视频|R语言bnlearn包:贝叶斯网络的构造及参数学习的原理和实例
|
13天前
|
算法 数据可视化 数据挖掘
课程视频|R语言bnlearn包:贝叶斯网络的构造及参数学习的原理和实例(上)
课程视频|R语言bnlearn包:贝叶斯网络的构造及参数学习的原理和实例
|
1天前
|
机器学习/深度学习 算法
应用规则学习算法识别有毒的蘑菇
应用规则学习算法识别有毒的蘑菇
|
2天前
|
机器学习/深度学习 存储 自然语言处理
【威胁情报挖掘-论文阅读】学习图表绘制 基于多实例学习的网络行为提取 SeqMask: Behavior Extraction Over Cyber Threat Intelligence
【威胁情报挖掘-论文阅读】学习图表绘制 基于多实例学习的网络行为提取 SeqMask: Behavior Extraction Over Cyber Threat Intelligence
6 0
|
4天前
|
算法
【免费】面向多微网网络结构设计的大规模二进制矩阵优化算法
【免费】面向多微网网络结构设计的大规模二进制矩阵优化算法
|
12天前
|
机器学习/深度学习 算法 数据挖掘
【Python机器学习专栏】关联规则学习:Apriori算法详解
【4月更文挑战第30天】Apriori算法是一种用于关联规则学习的经典算法,尤其适用于购物篮分析,以发现商品间的购买关联。该算法基于支持度和置信度指标,通过迭代生成频繁项集并提取满足阈值的规则。Python中可借助mlxtend库实现Apriori,例如处理购物篮数据,设置支持度和置信度阈值,找出相关规则。
|
12天前
|
机器学习/深度学习 算法 前端开发
【Python机器学习专栏】集成学习算法的原理与应用
【4月更文挑战第30天】集成学习通过组合多个基学习器提升预测准确性,广泛应用于分类、回归等问题。主要步骤包括生成基学习器、训练和结合预测结果。算法类型有Bagging(如随机森林)、Boosting(如AdaBoost)和Stacking。Python中可使用scikit-learn实现,如示例代码展示的随机森林分类。集成学习能降低模型方差,缓解过拟合,提高预测性能。
|
12天前
|
Kubernetes API 调度
|
13天前
|
前端开发 数据挖掘 数据建模
课程视频|R语言bnlearn包:贝叶斯网络的构造及参数学习的原理和实例(中)
课程视频|R语言bnlearn包:贝叶斯网络的构造及参数学习的原理和实例
|
14天前
|
机器学习/深度学习
GAN网络的代码实现(学习ing)
GAN网络的代码实现(学习ing)