网络流Dinic(本篇介绍最大流)

前言:看到网上Dinic和ISAP的比较,多数人认为ISAP更快,不容易爆栈。当然,也有少数人认为,在多数情况下,Dinic比较稳定。我认为Dinic的思路比ISAP更简明,所以选择了Dinc算法

介绍:Dinic算法本身,自然是解决最大流(普通最大流,最大流最小割)的算法。通过处理,也可以解决二分图的最大匹配(下文介绍),最大权闭合图。

算法介绍:介绍Dinic之前,我们先介绍一下最大流。在最大流的题目中,图被称为"网络",每条边的边权被称作"流量",有一个起点(源点)和一个终点(汇点)。我们要求的最大流,可以这样形象地理解:源点有一个水库,里面有无限吨水(QWQ),汇点也有一个水  库,希望得到最多的水。我们假设每个河道一天只能输水n吨(及网络流中的流量),求解汇点最多能的到几吨水。再给一个正式的定义:最大流是指网络中满足弧流量限制条件和平衡条件且具有最大流量的可行流

下面我们正式介绍Dinic:

首先引出网络流算法中的链,给个正式定义:链是网络中的一个顶点序列,这个序列中前后两个顶点有弧相连(其实我认为这个定义无关紧要,所以重点看下面弧的定义)。

弧 :弧分为两种,第一种是前向弧是指方向和链一致的弧(简单的说就是输入的边)---前向弧,第二种弧是指方向和链不一致的弧(简单的说就是输入的边反一反)---后向弧。

好了接下来要引出一个网络流算法的重要概念

增广路:

给个正式的定义:

1、增广路是一条链

2、链上的前向弧都是非饱和弧

链上的后向弧都是非零弧

3、链是由源点到汇点的

总结一下:额...这听起来好像啥都没说(滑稽)

谈谈我的理解:

增广路就是一条从源点到汇点的路,并且带有一个值,表示该增广路的最大流量,该值得大小取决于该增广路中拥有最小流量的边。

最大流中一个很重要的网络叫做剩余网络,就是由反向弧组成的网络,关于反向弧的权的问题,后文会介绍。

说了一大堆,现在正式介绍Dinic算法

Dinic算法的大致步骤

1、建立网络(包括正向弧和反向弧(初始边权为0)),将总流量置为0

2、构造层次网络(怎么又有新概念 T_T)

简单的说,就是求出每个点u的层次,u的层次是从源点到该点的最短路径(注意:这个最短路是指弧的权都为1的情况下的最短路),若与源点不连通,层次置为-1

一遍BFS轻松解决

3、判断汇点的层次是否为-1

是:再见,算法结束,输出当前的总流量

否:下一步

4、用一次DFS完成所有增广,增广是什么呢?

增广(我的理解):通过DFS找上述的增广路,找到了之后,将每条边的权都减去该增广路中拥有最小流量的边的流量,将每条边的反向边的权增加这个值,同时将总流量加上这个值

DFS直到找不到一条可行的从原点到汇点的路

5、goto 步骤2

细节处理,如何快速找到一条边的反向边:边的编号从0开始,反向边加在正向边之后,反向边即为该点的编号异或1

复杂度:理论上来说,最慢应该是O((n^2)*m),n表点数,m表边数,实际上呢,应该快得不少

代码实例:(参见洛谷P3376)

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>

using namespace std;

const int MAX = (1 << 31) - 1;

struct Edge{
    int to;
    int dis;
    int next;
} edges[210000];

int head[10010], edge_num = -1;
int n, m, s, t;

void add_edge_2(int from, int to, int dis)
{
    edges[++edge_num].to = to;
    edges[edge_num].dis = dis;
    edges[edge_num].next = head[from];
    head[from] = edge_num;
}

void add_edge(int from, int to, int dis)
{
    add_edge_2(from, to, dis);
    add_edge_2(to, from, 0);
}

//层次
int d[10010];

int DFS(int u, int flow)
{
    if (u == t)
        return flow;
    int _flow = 0, __flow;
    int c_e = head[u], v;
    while (c_e != -1)
    {
        v = edges[c_e].to;
        if (d[v] == d[u] + 1 && edges[c_e].dis > 0)
        {
            __flow = DFS(v, min(flow, edges[c_e].dis));
            flow -= __flow;
            edges[c_e].dis -= __flow;
            _flow += __flow;
            edges[c_e^1].dis += __flow;
            if (flow == 0)
                break;
        }
        c_e = edges[c_e].next;
    }
    if (_flow == 0)
        d[u] = -1;
    return _flow;
}

bool BFS()
{
    memset(d, -1, sizeof(d));
    queue<int> que;
    d[s] = 0;
    que.push(s);
    int _now, c_e, _new;
    while (!que.empty())
    {
        _now = que.front();
        que.pop();
        c_e = head[_now];
        while (c_e != -1)
        {
            _new = edges[c_e].to;
            if (d[_new] == -1 && edges[c_e].dis > 0)
            {
                d[_new] = d[_now] + 1;
                que.push(_new);
            }
            c_e = edges[c_e].next;
        }
    }
    if (d[t] != -1)
        return true;
    else
        return false;
}

void dinic()
{
    int max_flow = 0;
    while (BFS())
    {
        max_flow += DFS(s, MAX);
    }
    printf("%d", max_flow);
}

int main()
{
    scanf("%d %d %d %d", &n, &m, &s, &t);
    memset(head, -1, sizeof(head));
    int i, t1, t2, ds;
    for (i = 0; i < m; i++)
    {
        scanf("%d %d %d", &t1, &t2, &ds);
        add_edge(t1, t2, ds);
    }
    dinic();
    return 0;
}

算法主要应用场景

1、裸的最大流

2、二分图的最大匹配:建一个点S,连到二分图的集合A中;建一个点T,连到二分图的集合B中。再将所有的集合A中的点与集合B中的点相连。全部边权设为1,跑一遍最大流,结果即为二分图的最大匹配

3、最小割(定义自行百度):在单源单汇流量图中,最大流等于最小割

4、求最大权闭合图(定义自行百度):最大权值=正点权之和-最小割

主要问题:

  为什么要建立反向边?

  Answer:总结多篇博客,认为建立反向边旨在增加重新调整流的机会,即保障解是最优的(还是没有理解?可以自行百度:D)。

原文地址:https://www.cnblogs.com/linzhengmin/p/9313216.html

时间: 2024-08-30 05:50:07

网络流Dinic(本篇介绍最大流)的相关文章

最大流(网络流)基础篇(剪辑)

网络流初步总结 查看资料:lrj <算法竞赛入门经典> 相关概念: 最大流:(Maximum-Flow Problem) 从源点 S  中间经过一些点,一些的物品运送到汇点 t . 中途每两点间都有个最大运送物品数. 求从 s 到 t 最多能运送多少物品. 容量: 对于一条边 (u,v),它的物品上限(能够运送的物品最大数量)称为容量 (capacity), 记为 c(u,v) (对于不存在的边 (u,v) , c(u,v) = 0) 流量: 实际运送物品数称为流量 (flow) 规定:f(u

hdu2732 Leapin&#39; Lizards (网络流dinic)

D - Leapin' Lizards Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description Your platoon of wandering lizards has entered a strange room in the labyrinth you are exploring. As you are looking around for hidden treasur

hdu 3572 Task Schedule(网络流 dinic算法)

Task Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3412    Accepted Submission(s): 1197 Problem Description Our geometry princess XMM has stoped her study in computational geometry t

iOS开发UI篇—自定义瀑布流控件(接口设计)

iOS开发UI篇—自定义瀑布流控件(接口设计) 一.简单说明 1.关于瀑布流 电商应用要展示商品信息通常是通过瀑布流的方式,因为每个商品的展示图片,长度和商都都不太一样. 如果不用瀑布流的话,展示这样的格子数据,还有一种办法是使用九宫格. 但利用九宫格有一个缺点,那就是每个格子的宽高是一样的,如果一定要使用九宫格来展示,那么展示的商品图片可能会变形. 为了保证商品图片能够按照原来的宽高比进行展示,一般采用的是瀑布流的方式. 2.瀑布流的特点: 由很多的格子组成,但是每个格子的宽度和高速都是不确定

win7扫盲篇--介绍安装(1)

1.硬件+操作系统+软件应用=用户电脑 2.win7  2007年 winXP 2001年  不能兼容64位 win98 1998年 UNIX  银行操作系统 Linux开源自由的操作系统,安全稳定比较出色,在服务领域使用广泛,安卓是基于Linux操作系统 Mac OS苹果操作系统 MS-DOS 命令行操作 3.win7版本 win7家庭普通版的功能最少,简装版本 win7旗舰版,功能最多 硬件需求 cpu1GH以上,内存1G以上,硬盘16G以上,32位最多支持3个G得内存 cpu1GH以上,内

POJ 1273 Drainage Ditches (网络流Dinic模板)

Description Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by water for awhile and takes quite a long time to regrow. Thus, Farmer John has built a set of drainage

iOS开发UI篇—自定义瀑布流控件(蘑菇街数据刷新操作)

iOS开发UI篇—自定义瀑布流控件(蘑菇街数据刷新操作) 一.简单说明 使用数据刷新框架: 该框架提供了两种刷新的方法,一个是使用block回调(存在循环引用问题,_ _weak),一个是使用调用. 问题:在进行下拉刷新之前,应该要清空之前的所有数据(在刷新数据这个方法中). 移除正在显示的cell: (1)把字典中的所有的值,都从屏幕上移除 (2)清除字典中的所有元素 (3)清除cell的frame,每个位置的cell的frame都要重新计算 (4)清除可复用的缓存池. 该部分的代码如下: 1

[网络流dinic]日常翻新

之前的排版简直辣眼睛,重写一遍好了 模板题是草地排水poj1273 网络流的基础思想就是瞎基本搜 但是搜要搜得有技巧,有特色 最简单的搜,无限深搜直到终点 稍微改进一下,宽搜先标号然后按层搜 再改进一下,把某些确定不再使用的点剔除 要点在于建立反向边给自己一个反悔的机会,用^1找到反向边 #include <stdio.h> #include <queue> #include <algorithm> #include <string.h> using nam

iOS开发UI篇—自定义瀑布流控件(基本实现)

iOS开发UI篇—自定义瀑布流控件(基本实现) 一.基本实现 说明:在View加载的时候,刷新数据. 1.实现代码 YYViewController.m文件 1 // 2 // YYViewController.m 3 // 06-瀑布流 4 // 5 // Created by apple on 14-7-28. 6 // Copyright (c) 2014年 wendingding. All rights reserved. 7 // 8 9 #import "YYViewControll