网络流自学心得[dinic算法]

今天来讲讲dinic算法。

在学习dinic算法之前,我觉得我们可以先学学链式前向星的数据结构。在做题的过程中,很多题目卡内存,再用邻接矩阵不太现实。
链式前向星
链式前向星2
之前一直不懂链式前向星的遍历,那个head数组看不懂,所以在学习的时候,最好拿出笔把那个数组给画出来,然后在遍历的时候一一找遍历时候对应的边,就会发现他遍历时候的一个顺序。

好了 然后重点。我们dinic算法。

dinic算法

dinic算法呢是一个叫Dinitz的人提出的,而这种算法和ek算法的不同在于,他发现了一种新的找增广路的新的办法。即先对图进行分层,找增广路的时候就能沿着分好层的图一步一步往前走。

下面是这个算法的一个做法。

  1. BFS ——> 遍历一遍每一个点,对图进行分层。。
  2. DFS ——> 进行增广,找一条链。 然后在dfs里面我们对起点的那几条边进行一个遍历,就可以进行多次增广。
  3. dinic ——> 将BFS 和DFS 组合在一起。
typedef struct Edge{
    int u, v, c, next;
}edge;

void adde(int u, int v, int c){
        e[hcnt].u = u; e[hcnt].v = v;e[hcnt].c = c;
        e[hcnt].next = head[u]; head[u] = hcnt ++;
        e[hcnt].u = v; e[hcnt].v = u;e[hcnt].c = 0;
        e[hcnt].next = head[v]; head[v] = hcnt ++;
    }
  //链式向前星的一些操作。 增边的时候可以把反边也加一下。
  //这里用了一个小技巧  我们把一个偶数一个奇数进行组合,比如 01  23 34   这样把一个边与1进行异或的时候,就是另一条边。
bool bfs(){
        queue <int> q;
        memset(dep, -1, sizeof (dep));//每次进来的时候一定要把图层刷新一遍
        q.push(S); dep[S] = 0;
        while (!q.empty()){
            int h = q.front(); q.pop();
            if (h == T) return true;

            for (int i=head[h]; ~i; i=e[i].next){
                int v = e[i].v;
                if (dep[v] != -1 || e[i].c <= 0) continue;
                dep[v] = dep[h] + 1;
                q.push(v);
            }
        }

        return false;
    }
    //BFS进行分层操作
int dfs(int s, int mw){
        if (s == T) return mw;   //遇到汇点我们就返回
        if (mw == 0) return mw;//如果到这里的流是0了 也没有必要走下去了、

        int flow = 0;
        for (int i=head[s]/*(cur[s])*/; ~i; i = e[i].next){
            //cur[s] = i;
            int v = e[i].v;
            if (dep[v] == dep[s] + 1 && e[i].c > 0){
                flow = dfs(v, min(mw, e[i].c));
                if (flow > 0){
                    e[i].c -= flow;
                    e[i^1].c += flow;
                    return flow;
                }
            }
        }
       return 0;
    }
 int dinic(){
     int ans = 0;
     while (bfs()){
       //  for (int i=0; i<N; i++) cur[i] = head[i];
         int v = dfs(1, INF);
         ans += v;
     }
     return ans;
 }

所以dinic算法所要做的事情就是一个dfs 一个bfs。。

然后dinic算法有两个优化。。
1.当前弧优化
2.当我们bfs第一次遇到汇点的时候,我们就可以直接返回true。

弧优化的代码我已经写在了上面的代码里面,而这大概是一个什么东西呢。。
就是刚开始的算法里面,我们在找增广路的时候,我们依然还在考虑已经增广过得路,即已经走过了的不能再走的了那条空路。
而当前弧优化,就是开个数组把这个东西存一存,每次我们从当前弧开始走就行了。

至于第二个优化,貌似有论文证明了,我也就没有操心了= =、 能力有限。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值