• 网络流之最大流


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

      最近一鼓作气终于会最大流的(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;
    }

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

  • 相关阅读:
    bash:express:command not found
    Jquery的window.onload实现
    元素的class和id问题
    安装angular-cli
    [(ngModel)]的实现原理
    bodyparser
    git push不用重复输入用户名和密码(解决方案)
    git提交项目到已存在的远程分支
    angular的$filter服务
    网站上如何添加显示favicon
  • 原文地址:https://www.cnblogs.com/cjjsb/p/8576030.html
Copyright © 2020-2023  润新知