下面介紹兩種時間複雜度較為優秀的網路流演算法: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無法進行下去的時候...