1. 程式人生 > >關於dinic演算法中當前弧如何優化問題

關於dinic演算法中當前弧如何優化問題

剛開始學最大流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;
        }

鄙人語言能力不強,能力有限,如果有錯誤和漏洞,請各位大佬批評指正,謝謝。