較優的網路流演算法

2021-09-26 04:40:57 字數 1398 閱讀 4868

下面介紹兩種時間複雜度較為優秀的網路流演算法:dinic和sap。

dinic主要是以下兩大優化:

分層當前弧優化

每一次dfs之前我們都從源點bfs一次,bfs只走還剩流量可流的邊,通過bfs我們把殘量網路分層。設i的深度為deep[i],那麼在dfs是我們要保證deep[y]=deep[x]+1才走x-y這條邊。

當然我們也可以多次dfs再一次bfs,這也不影響正確性。

這個其實就是記錄一下每乙個點當前增廣到那一條邊了,下一次直接從這條邊開始增廣即可。注意每次改變deep時都要把所有的當前弧清零,因為可用的邊發生了變化。

這個優化看似沒有多大用,但是實際上可以大大提高效率。

sap其實就是dinic的進化版。在dinic時我們需要多次bfs來求deep,而在sap時我們不妨在dfs中實時更新deep。

sap的核心思路是:當乙個點無法增廣時,我們要更新它的deep使得它又有可能增廣。

往上說的操作是把deep改為連出去的兒子的deep的min-1,但是我身邊的同學打的都是把deep全部初始賦為0,然後每次+1(或者把deep全部賦為n,然後每次-1)。

當一種deep的個數變為0的時候,這就標誌著增廣完畢了。因為如果一種deep的個數變為0,那麼就說明deep圖出現了斷層。在這種情況下是不可能增廣成功的。

最後要注意的是,每次修改乙個乙個點的deep時,都要把它的當前弧優化的陣列清零。

下面貼一下**:

#include#include#include#define maxn 1010

#define maxm 1000010

struct map

;map way[maxm];

int first[maxn],nxt[maxm],num[maxn],deep[maxn],cur[maxn],pre[maxn],n,m,ans,tf=1,w;

int dfs(int z)

return 100;

} else

cur[z]=nxt[cur[z]];

} num[deep[z]]--;if(num[deep[z]]==0)

deep[z]--;num[deep[z]]++;

cur[z]=first[z];

} return 50;

}int main()

m*=2;for(i=m;i>=1;i--)nxt[i]=first[way[i].x],first[way[i].x]=i;

for(i=1;i<=n;i++)deep[i]=n;

for(i=1;i<=n;i++)num[deep[i]]++;

for(i=1;i<=n;i++)cur[i]=first[i];

while(true)

printf("%d",ans);

}

網路流演算法

問題描述 如圖4 1所示是聯結某產品地v1和銷售地v4的交通網,每一弧 vi,vj 代表從vi到vj的運輸線,產品經這條弧由vi輸送到vj,弧旁的數表示這條運輸線的最大通過能力。產品經過交通網從v1到v4。現在要求制定乙個運輸方案使從v1到v4的產品數量最多。圖 4 1 圖 4 2 一 基本概念及相...

網路流演算法

ek演算法模板 演算法複雜度 n m m n為點數,m為邊數 源點 1,匯點 n。const int maxn 310,inf 0x7fffffff int pre maxn mat maxn maxn bool vis maxn int n,m int augment else q.push ba...

網路流演算法

網路流演算法 網路流演算法用於解決從源點到匯點最大流的問題。edmonds karp演算法 演算法主要思想 每次bfs找到一條從源點到匯點的最少路徑數的可行路徑,同時把這條路徑塞滿,這條路上的最小容量即為這條路徑的流量。然後將這條路徑的正向邊刪除,增加一條容量相同的反向邊,當bfs無法進行下去的時候...