zoukankan      html  css  js  c++  java
  • HDU 1532 (Dinic算法)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1532

    题目大意:

          就是由于下大雨的时候约翰的农场就会被雨水给淹没,无奈下约翰不得不修建水沟,而且是网络水沟,并且聪明的约翰还控制了水的流速,本题就是让你求出最大流速,无疑要运用到求最大流了。题中N为水沟数,M为水沟的顶点,接下来Si,Ei,Ci分别是水沟的起点,终点以及其容量。求源点1到终点M的最大流速。注意重边。

      这是Dinic算法,该算法的效率很高,复杂度O(m*n^2)。

      Dinic算法的实现有以下几个步骤:

      1:初始化容量网络和网络流

      2:构造残留网络和层次网络,若汇点不在层次网络中则算法结束 输出最大流

      3:在层次网络中用一次DFS进行增广,DFS执行完毕,该阶段的增广也就完毕了。

      4:转至步骤2

    参考代码:

    #include<iostream>  
    #include<cstdio>  
    #include<queue>  
    #include<cstring>
    using namespace std;  
    
    #define INF 0x7fffffff  
    #define min(a,b) a<b?a:b  
    int N,M;  
    int level[205];  
    int Si,Ei,Ci;  
    struct Dinic  
    {  
        int c;  
        int f;  
    }edge[205][205];  
    bool dinic_bfs()//构造层次网络  
    {  
        queue<int> Q;  
        memset(level,0,sizeof(level));//初始化顶点的层次 为0  
        Q.push(1);  
        level[1]=1;  
        int u,v;  
        while(!Q.empty())  
        {  
            u=Q.front();  
            Q.pop();  
            for(v=1;v<=M;v++)  
            {  
                if(!level[v]&&edge[u][v].c>edge[u][v].f)//即顶点未被访问过,顶点u,v,存在边  
                {  
                    level[v]=level[u]+1;//给顶点标记层次  
                    Q.push(v);  
                }  
            }  
        }  
        return level[M]!=0;//若返回false表明 汇点不在层次网络中  
    }  
    int dinic_dfs(int u,int cp)//进行增广  
    {  
        int tmp=cp;  
        int v,t;  
        if(u==M)  
            return cp;  
        for(v=1;v<=M&&tmp;v++)  
        {  
            if(level[u]+1==level[v])  
            {  
                if(edge[u][v].c>edge[u][v].f)  
                {  
                    t=dinic_dfs(v,min(tmp,edge[u][v].c-edge[u][v].f));  
                    edge[u][v].f+=t;  
                    edge[v][u].f-=t;  
                    tmp-=t;  
                }  
            }  
        }  
        return cp-tmp;  
    }  
    int dinic()//求出最大流  
    {  
        int sum,tf;  
        sum=tf=0;  
        while(dinic_bfs())  
        {  
            while(tf=dinic_dfs(1,INF))  
            {  
                sum+=tf;  
            }  
        }  
        return sum;  
    }  
    int main()  
    {  
        while(~scanf("%d%d",&N,&M))  
        {  
            memset(edge,0,sizeof(edge));  
            while(N--)  
            {  
                scanf("%d%d%d",&Si,&Ei,&Ci);  
                edge[Si][Ei].c+=Ci;//防止重边  
            }  
            int S=dinic();  
            printf("%d
    ",S);  
        }  
        return 0;  
    }  
  • 相关阅读:
    【OpenXml】Pptx的边框虚线转为WPF的边框虚线
    C#系列文章索引
    了解LINQ
    【爬虫系列】2. 打开App逆向“潘多拉魔盒”
    Makefile基础
    设计原则 开闭原则
    设计模式 工厂方法模式
    设计原则 接口隔离原则
    设计原则 迪米特法则
    设计原则 单一职责原则
  • 原文地址:https://www.cnblogs.com/s1124yy/p/5646564.html
Copyright © 2011-2022 走看看