Dinic

Dinic算法


dinic算法就是优化版本的ford-Fulkenson算法,不同是每次时寻找最短增广路增广,因为最短增广路在DFS的增广过程中是不会再变短的,所以可以进行多次的DFS,直到最短增广路长度变长或者不存在增广路了,这样子的得到的流称为阻塞流。

​ 每次构建层次图的时间复杂度是|E|,而最短增广路的深度时不会超过顶点数V-1的,所以操作最多重复O(|V|)次。

​ 在算法中每次对边进行检查是否走过,在此使用当前弧优化,可以避免重复不必要的检查。降低算法复杂度。


1、Dinic算法思路

Dinic算法的思想也是分阶段地在层次网络中增广。它与最短增广路算法不同之处是:最短增广路每个阶段执行完一次BFS增广后,要重新启动BFS从源点Vs开始寻找另一条增广路;而在Dinic算法中,只需一次DFS过程就可以实现多次增广,这是Dinic算法的巧妙之处。Dinic算法具体步骤如下:

(1)初始化容量网络和网络流。

(2)构造残留网络和层次网络,若汇点不再层次网络中,则算法结束。

(3)在层次网络中用一次DFS过程进行增广,DFS执行完毕,该阶段的增广也执行完毕。

(4)转步骤(2)。


在Dinic的算法步骤中,只有第(3)步与最短增广路相同。在下面实例中,将会发现DFS过程将会使算法的效率有非常大的提高。
摘录自Fei Guo Dinic算法详解及实现感觉解释的很不错,在此记录学习。


#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <queue>
using namespace std;
const int inf = 0x3f3f3f3f;
const int maxn = 1000;
struct Edge
{
    int from,to,cap,flow;
    Edge(int f,int t,int w,int flow):from(f),to(t),cap(w),flow(flow) {}
};
struct Dinic
{
    int s,t;
    vector<Edge> edges;
    vector<int> G[maxn];
    int color[maxn],level[maxn];
    int cur[maxn];
    void init()
    {
        edges.clear();
        for(int i=0; i<maxn; i++) G[i].clear();
    }

    void addedge(int n,int m)
    {
        int x,y,w;
        for(int i=0; i<m; i++)
        {
            scanf("%d%d%d",&x,&y,&w);
            edges.push_back(Edge(x,y,w,0));
            edges.push_back(Edge(y,x,0,0));
            int len = edges.size();
            G[x].push_back(len-2);
            G[y].push_back(len-1);
        }
    }

    int bfs()
    {

        memset(color,0,sizeof(color));
        color[s] = 1;
        queue<int> q;
        level[s]=0;
        q.push(s);
        while(!q.empty())
        {

            int u = q.front();q.pop();
            int len = G[u].size();
            for(int i=0; i<len; i++)
            {
                Edge e = edges[G[u][i]];
                if(!color[e.to] && e.cap>e.flow  )
                {

                    color[e.to] = 1;
                    q.push(e.to);
                    level[e.to] = level[u]+1;
                }
            }
        }
        return color[t];
    }

    int dfs(int x,int a){
        if(x==t || a==0 )
            return a;
        int flow=0,f;
        int len = G[x].size();
        for(int &i=cur[x] ; i<len;i++){
            Edge &e = edges[G[x][i]];
            if(level[e.to] == level[x]+1 &&(f = dfs(e.to,min(a,e.cap-e.flow) ) )>0 ){
                e.flow +=f;
                flow+=f;
                edges[G[x][i]^1].flow -= f;
                a-=f;
                if(a==0)break;
            }
        }
        return flow;
    }

    int maxflow(int s,int t){
        this->s = s;
        this->t = t;
        int flow = 0;
        while(bfs()){
            memset(cur,0,sizeof(cur));
            int f=0;
            while(f=dfs(s,inf)) flow+=f;
        }
        return flow;
    }

};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值