浅析网络流(包懂)

本文深入浅出地介绍了网络流的基本概念、最大流的EK算法及其实现,包括最小费用最大流和最小割最大流,以及它们在实际问题中的应用,如二分图匹配和费用流问题。
摘要由CSDN通过智能技术生成

网络流

0.序言

听起来这个名字如此高级,其实不然,大家要抱着一种开放包容的心态去学它。

一.基本概念

先来见一下网络流的基本图形:
在这里插入图片描述
可以看到,网络流的图形有一个源点s和一个汇点t,每一条边都有一个容量和流量,流量永远小于或等于容量。

二.预备知识

网络流必须要用数组模拟指针的方法去存图,不能用vector哟。
推荐博起:数据结构之邻接表

三.最大流

1.概念

在这里插入图片描述
最大流就是说要求从源点到汇点最大的流量,这个图显而易见,最大流就是15,图中已经标出来了。
那么怎么计算这个最大流呢?

2. EK算法

1.思想

很容易想到一个有些暴力的算法:从源点开始,暴力的找出所有到汇点的路径,再把每条路径上最小的边的容量加起来就行了。
每条能贡献流量的路就叫做增广路。
但是这种方法的正确性有待考究,比如这个图:
在这里插入图片描述
假如我们先走s→1→4→t,图就变成了这样:
在这里插入图片描述
然后走s→2→4→t,发现4→t的时候路被堵了,但是上一条路径明明可以改成s→1→3→t,这样这一条路就可以顺利走通了,并且找到了最大流,就是20,如下图:
在这里插入图片描述
现在最难得问题就是怎么来实现这个算法呢?
现在,引入一种算法:建反边
那么,原图就变成了这个样子(初始化所有反边容量为0):
在这里插入图片描述
每走过一条边,就让你走的方向的边的容量减去流量,让反向的边的容量加上流量就行了。最后你找最大流的时候,就直接在图中从s到t走,找出所有增广路(你建的所有的边都可以走),像最初我们的想法那样做就行了。
总结起来,分三步:
1.建反向边
2.找所有增广路
3.统计最大流

这就叫做EK算法。
那为什么要建反边呢?个人认为是为了让路径上遇到容量不允许的边能够改变原来走那条边的路径,让那条路径去找其它可能的边去走,如果找不到,就让这条路径终止,那条路径不变。额。。。大家可以去找找其它的证明康康。

2.实现

先说找增广路:
因为我们要存储这条路径,所以要用pre[x]去存经过点x的路径的前一个点,和点x与前一个点相连的边的编号(要用数组模拟指针去存图哟)。
上代码:

struct node {
   
    int x, edge;
    node (){
   };
    node (int X, int Edge){
   
        edge = Edge;
        x = X;
    }
}pre[N];
bool find (){
   
    queue <int> Q;
    Q.push (s);
    memset (vis, 0, sizeof vis);
    memset (pre, -1, sizeof pre);
    vis[s] = 1;
    while (! Q.empty ()){
   
        int f = Q.front ();
        Q.pop ();
        for (int i = first[f]; i != -1; i = next[i]){
   
            if (! vis[v[i]] && w[i]){
   
                pre[v[i]].x = f;
                pre[v[i]].edge = i;
                if (v[i] == t)
                    return 1;
                vis[v[i]] = 1;
                Q.push (v[i]);
            }
        }
    }
    return 0;
}

再来说说统计最大流:
很简单,先沿着找到的增广路找出最小容量的边的容量作为流量,再把路径上的边的容量减去流量,反边加上流量就行了。

void EK (){
   
    while (find ()){
   
        int minn = INF;
        for (int i = t; i != s; i = pre[i].x
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值