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;
}
};