关于最大流 Dinic 算法的一些理解。

    技术2025-01-20  4

    小媛原创啊,哇咔咔~~

     

    1、剩余图,简单来说即边的容量为总容量 - 当前流量。

     

    2、层次图,即从源点开始,生成的一颗BFS树,可以这么理解,树的高度 - 当前树的高度即为层次编号。

     

    由此可知,层次图的构建需要用BFS去找,相当于BFS的时间戳了都。

     

    而dinic的BFS函数是判断汇点是否在从源点开始找的层次图里。

     

    我觉得dinic与EK的区别之处在于,EK是用BFS去找增广路,而dinic是在层次图里用DFS找增广路。

     

    引用下http://acm.hrbeu.edu.cn/forums/index.php?showtopic=3003这个里面的一段话

     

     


     

     

        采用DFS非递归的形式实现找增广路。也许你蒙了,这怎么还用DFS啊,明显不如BFS啊。但是你别忘了,你现在是在标号后的图中找增广路,DFS实际上也不必BFS差到哪里去。而且DFS的优点在于它可以找到所有的路径,这个是BFS无法媲美的。这样实现,我们就可以充分的利用了第一步的标号了。也许你会明白我的意思了,我们可以用一次标号找出多条增广路。这样的话效率不就大大的提高了。

     

     


     

     

    那么如何去找呢 ?

     

    类似于DFS,如果找到一个节点在层次图中,用它往下延伸,一直延伸到汇点,如果存在,就在这条路上找最小容量,增广之。

     

    如果增广后,容量满了,阻塞之,实现方法即把这个点在层次图里的编号赋为其它点到不了的值,比如INT_MAX,-1。

     

    如果不能到达汇点,这个节点返回上一层,继续找。

     

    如果这个点都找完后(即上一层到达源点),再BFS从源点建立新的层次图,继续找。。。直到汇点不在新的层次图里结束。

     

    int cap[MAX][MAX]; int lev[MAX]; queue<int> q; int BFS(int s,int t) { int u,v; memset(lev,-1,sizeof(lev)); q.push(s); lev[s] = 0; while( !q.empty() ) { u = q.front(); q.pop(); for(v=0; v<=t; v++) if( cap[u][v] > 0 && lev[v] == -1 ) { lev[v] = lev[u] + 1; q.push(v); } } return lev[t] != -1; } int Dinic(int s,int t) { int a[MAX],cur[MAX]; int pre[MAX]; int flow = 0; int i,u,flag,v,ag,k; while( BFS(s,t) ) { for(i=0; i<=t; i++) { // cur里初始化是第一个节点哈 cur[i] = 0; // DFS中,如果需要回溯,就回溯到cur中的节点。 a[i] = INT_MAX; // a里面存的是剩余流量 } u = s; while(1) { flag = 0; for(v=cur[u]; v<=t; v++) if( cap[u][v] > 0 && lev[u] + 1 == lev[v] ) { flag = 1; break; } if( flag ) { cur[u] = v + 1; pre[v] = u; a[v] = cap[u][v]; if( a[v] > a[u] ) a[v] = a[u]; u = v; // 从找到的节点后开始在层次图里找路 if( u == t ) // 找到t后,增广 { ag = a[t]; flow += ag; for(v=t; v!=s; v=pre[v]) { cur[pre[v]] = v; // 退回上一步。。 cap[pre[v]][v] -= ag; cap[v][pre[v]] += ag; a[v] -= ag; if( cap[pre[v]][v] == 0 ) u = pre[v]; } } } else if( u != s ) // 如果u != s 那么这条路走不通的话,从u的上一个节点继续找。 { lev[u] = INT_MAX; // 相当于从层次图里删除这个节点。 u = pre[u]; } else // 如果从源点找不到增广路,就结束咧。 break; } } return flow; } 

    最新回复(0)