zoukankan      html  css  js  c++  java
  • 网络流之最大流

      网络流之前一直尝试去学过好多次,但一直都没搞懂。

      最近一鼓作气终于会最大流的(fuck)

      其实有些时候可能真的一瞬间就理解了些东西(上语文课的时候突然理解增广路了)

      也推荐一些学习的博客(我们不生产资料,我们只是资料的搬运工):

      关于网络流十分形象的解读以及一些基本概念:http://blog.csdn.net/txl199106/article/details/64441994

      关于EK及原理的解释(图很多,虽然有了Dinic要EK也没什么用):https://www.cnblogs.com/zsboy/archive/2013/01/27/2878810.html

      Dinic(讲的很好,结构很好,总之很好):https://www.cnblogs.com/zsboy/archive/2013/01/27/2878810.html

      因为我太弱,搞不来图片,用画图又太丑。

      只能草率的讲一讲思想(个人理解)

      

      EK:虽然没什么用,但复杂度还可以接受。

      1.在残量网络中找到一条从S到T的增广路,如果没有则结束该算法。

      2.更新这条路上的边,正向边减,反向边加上最小值即可。

      3.重复1,2

      其实EK还是很简单的,主要是看代码理解一下:

    inline int BFS(int s,int t)
    {
        memset(pre,-1,sizeof(pre));
        memset(f,0,sizeof(f));
        int H=0,T=1;
        q[1]=s; pre[s]=0; f[s]=1e9;
        while (H<T)
        {
            int now=q[++H];
            for (int i=1;i<=n;++i)
            if (i!=pre[now]&&pre[i]==-1&&c[now][i]>0)
            {
                pre[i]=now;
                f[i]=f[now]<c[now][i]?f[now]:c[now][i];
                q[++T]=i;
            }
        }
        return f[t]?f[t]:-1;
    }
    inline int max_flow(int s,int t)
    {
        memset(f,0,sizeof(f));
        int sum=0,inc;
        while ((inc=BFS(s,t))!=-1)
        {
            int now=t;
            while (now!=s)
            {
                c[pre[now]][now]-=inc;
                c[now][pre[now]]+=inc;
                now=pre[now];
            }
            sum+=inc;
        }
        return sum;
    }

      Dinic:非常好用的网络流算法,能解决几乎全部的网络流问题。

      同EK相似,只不过加上了分层图的一些概念。

      1.对整张图跑一遍BFS,记录每个点被访问的深度。

      2.通过DFS来找增广路,必须满足被扩展节点的深度为扩展节点深度+1。

      3.重复1,2。

      主要细节有几个:

      1.建边时从0开始编号,每次建两条(一正一反),这样对于每条边i它的反向边就是i^1

      2.如果在DFS时经过一个点已经没有增广路了,那么以后经过该点肯定也没有了。因此直接把深度清零即可。

      3.DFS时最好一次找多条增广路,可以加快速度。

      具体看代码:

    inline bool BFS()
    {
        memset(dep,0,sizeof(dep));
        dep[s]=1; q[1]=s;
        int H=0,T=1;
        while (H<T)
        {
            int now=q[++H];
            for (int i=head[now];i!=-1;i=e[i].next)
            if (!dep[e[i].to]&&e[i].c)
            {
                dep[e[i].to]=dep[now]+1;
                q[++T]=e[i].to;
            }
        }
        return dep[t];
    }
    inline int DFS(int now,int dist)
    {
        if (now==t) return dist;
        int res=0;
        for (int i=head[now];i!=-1&&dist;i=e[i].next)
        if (dep[e[i].to]==dep[now]+1&&e[i].c)
        {
            int dis=DFS(e[i].to,min(dist,e[i].c));
            dist-=dis; res+=dis;
            e[i].c-=dis; e[i^1].c+=dis;
        }
        if (!res) dep[now]=0;
        return res;
    }
    inline int Dinic()
    {
        int sum=0;
        while (BFS()) sum+=DFS(s,INF);
        return sum;
    }

      其实网络流难在建模,但要把板子打熟也是很重要的。

  • 相关阅读:
    CRM后期修改实体,新增货币类型字段 需要注意的问题
    CRM setValue方法日期类型字段赋值
    win10 ie11 以管理员身份运行才正常
    博客随缘更新,更多内容访问语雀知识库!
    解决Vulnhub靶机分配不到IP问题
    栈迁移原理图示
    【python】青果教务系统模拟登陆
    【二进制】CTF-Wiki PWN里面的一些练习题(Basic-ROP篇)
    2019"深思杯"山东省大学生网络安全技能大赛部分wp
    【web】docker复现环境踩坑
  • 原文地址:https://www.cnblogs.com/cjjsb/p/8576030.html
Copyright © 2011-2022 走看看