网络流Ford-fulkerson算法及dinic算法

当一个图中的每条边都拥有流量和最大流量时,我们一般就会求整个图的最大流量,这种问题就是网络流的最大流问题。

一开始我们考虑使用贪心,遍历一条路,找到整条路上的最大流量的最小值,储存,然后更新各点,当某边流量值等于最大流量值时,删除该边,再次遍历知道没有从源点到汇点的路径。

但经过简单的验证我们发现,以上的贪心算法算出的结果不一定是最优解。

原因是什么?

原因就是贪心过早地“填满了一条边”,从而“封锁了流量继续增加的可能”。

所以我们思考,能否将“不合理”的边删掉,从而继续搜索路径。但实际上,直接进行删除操作太过复杂,所以我们可以将原边的逆向边加在图中,这样就可以巧妙地删除不合理的边,从而求到最优解。

int dfs(int to,int t,int f)

{

if(to==t)return f;

vis[to]=1;

for(int i=first[to];i!=0;i=next[i]){

int v=go[i];

if(vis[v]==0&&data[i]>0){

int d=dfs(v,t,min(f,data[i]));

if(d>0){

data[i]-=d;

data[i^1]+=d;

return d;

}

}

}

return 0;

}

该方法使用的是纯DFS以上是DFS过程中的代码

但是我们应该注意一个问题纯DFS效率低下,耗时长

使用dfs找增广路

O(n+m)

做少增加1的流量;

最坏情况下要增加C次(C为边的容量和)

因此最多增加C

时间复杂度:

C*(m+n)C*n^2

所以我们可以用BFS进行分层,从而在找增广路时达到优化的效果,这就是网络流的dinic算法。

该算法的核心思想是:进行增广的时候,选择从源到汇的具有最少边数的增广路径。

事实证明这种算法的复杂度上限为nm 2  (n是点数,m是边数),所以dinic算法其实是要优惠很多的。

算法步骤如下:

1BFS对点进行分层;

2、从源点开始,用DFS从前一层向后一层反复寻找增广路(即要求DFS的每一步都必须要走到下一层的节点)

3、当找到汇点后,说明找到一条增广路,更新,进行增广;

4、增广后,不结束,回溯,继续找新的增广路;

5、当找不到增广路后,跳到第一步进行BFS,如果BFS无法找到汇点,则结束;

 

 

你可能感兴趣的:(网络流Ford-fulkerson算法及dinic算法)