刚开始学最大流dinic算法时,并没有运用优化,但是也解决了一些题。后来在做hdu的3572时,一直超时,被卡时间。所以上网查了下,了解到dinic中必须要加当前弧优化才可以过。然后查了下当前弧优化是什么鬼,网上的解释也是比较模糊,自己便思考了一番,于是说一下自己的想法。
当前弧优化就是为了防止走重复的边,从而较少了时间。
int dfs(int k,int y)
{
if(k==maxl+1)return y;
int f;
for(int i=cur[k]; i<V[k].size(); i++)
{
cur[k]=i;//如果这条路径可行,下次dfs到k顶点时从顶点k中编号为i的边开始找。
Lu L=Ed[V[k][i]];
if(L.flow>0&&dis[L.to]==dis[k]+1&&(f=dfs(L.to,min(y,L.flow))))
{
Ed[V[k][i]].flow-=f;
Ed[V[k][i]^1].flow+=f;
return f;
}
}
return 0;
}
我们知道dinic算法中的dfs是为了在可行增广路中找到最小容量。而找增广路需要遍历每个点所连接的边,直至找到一条可到达终点的路。例如,我们在第一次dfs时找到了一条增广路:顶点1中的第3条边,顶点2中的第4条边,顶点3中的第4条边,顶点5中的第2条边。这四条边是我们在第一次dfs寻找到的可行路,我们可以看到,每次找增广路时都是从某个顶点所连接的第一条边开始,那也就是说从顶点1中的第1条边接着去找没找到,从而遍历到顶点1中的第3条边,接着去找发现顶点2中的前三条边也没找到。。。这样下去直到找到终点。那么,我们可以知道下次dfs时,顶点1的前两条边没用(下次bfs或者几次bfs后可能会有用),直接从顶点1的第三条边开始去找。
当我们将当前图的所有增广路都找到后,再次bfs分层,当前图的层次会发生变化,然后我们在从顶点1开始去找,所以我们每次bfs,都要清一下数组cur。
while(bfs())
{
memset(cur,0,sizeof(cur));//清零,给以后的dfs记录
while(res=dfs(1,inf))ans+=res;
}
鄙人语言能力不强,能力有限,如果有错误和漏洞,请各位大佬批评指正,谢谢。