該演算法主要求的是,在乙個有向圖中,每條邊上有乙個最大流量,求從源點到匯點的最大流量。一般求解這類問題主要有以下幾種演算法。
增廣路ek演算法
這個演算法的主要思想很簡單,就是不斷bfs尋找增廣路並往裡頭新增流量,直到無法搜出增廣路,此時從源點流出的流量即為最大流。注意其中的反流量概念,即flow[u][v]=?flow[v][u]
該演算法時間複雜度上限為o(v?e2),不過一般到不了這個複雜度。
下面直接附上**:
#include
#include
#include
#include
using namespace std;
const int inf=1e+9;
const int maxn=200+10;
int c[maxn][maxn],f[maxn][maxn],p[maxn],pre[maxn],d[maxn<<4];
int main()
int flag=1;
while(flag)
}if(flag)break;
}if(!flag)break;
t=n;int min=inf;
while(pre[t])
}int ans=0;
for(i=1;i<=n;i++)
ans+=f[1][i];
printf("%d\n",ans);
return 0;
}dinic演算法
與ek演算法不同的是,dinic演算法每次要對有向圖進行一次bfs,對這張圖進行分層,得到圖上的每乙個點的層數。再進行dfs搜尋增廣路,增廣路只能從這一層到下一層。若不存在增廣路,則重複上述過程,對這張圖重新分層,直到無法搜到增廣路為止。
該演算法的時間複雜度的理論上限為o(n2m),不過同樣地,一般到不了這個複雜度。甚至在用dinic演算法做二分圖匹配時,複雜度能到o(n√?m)。
下面附上**:
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int inf=1e9;
const int maxm=1e5+10;
const int maxn=1e4+10;
int nex[maxm<<1],beg[maxm<<1],to[maxm<<1],flow[maxm<<1],q[maxn],lev[maxn];
int e=1,n;
inline int read()
inline void add(int x,int y,int z)
int bfs(int s,int t)
}return 0;
}int dfs(int x,int goal,int maxflow)
}return 0;
}int main()
int ans=0;
while(bfs(s,t))
ans+=dfs(s,t,inf);
printf("%d\n",ans);
return 0;
}isap演算法
isap演算法則在dinic演算法的基礎上又進行了一些優化。dinic演算法需要對殘餘流量進行多次分層,而isap只需要進行一次,甚至你可以不進行預處理分層(如下文中的**就沒有預處理分層)。dinic演算法在増廣後遇到沒有滿足條件的增廣路後,會對殘餘流量進行重新分層,而isap則會將level[x]重置為min(level[i])+1,其中i到x有一條有向邊。
但僅僅有這個優化是不夠的,isap的最大的優化來自gap優化。
gap優化就是看殘餘網路有無斷層的情況(即其中任何乙個節點都不屬於某一層),若有的話直接退出即可。
isap的優化是非常明顯的,在不開啟o2優化的情況下,洛谷模板題最大資料只需約80ms,而上文的dinic需要約900ms。
下面附上**:
#include
#include
#include
#include
using namespace std;
const int maxn=1e4+10;
const int maxm=2e5+10;
int flow[maxm],gap[maxn],dis[maxn],to[maxm],beg[maxm],nex[maxm];
int e=1,n,m,s,t;
void add(int x,int y,int z)
int isap(int x,int f)
if(!(--gap[dis[x]]))dis[s]=n;
gap[++dis[x]]++;
return f-res;
}int main()
int maxflow=0;
for(gap[0]=n;dis[s]這類問題在最大流問題的基礎上加上了乙個費用的引數,要求在流量最大的基礎上,費用最少。求出此時的流量與費用。
解決這類問題,一般採用ek與spfa相結合的演算法。
該演算法的主要思路,是在ek增廣路演算法的基礎上,使用spfa尋找費用最少的路徑,其餘基本與ek演算法相同。
下面附上**:
#include
#include
#include
#include
#include
using namespace std;
const int maxn=5e4+10;
const int inf=1e+9;
int to[maxn],nex[maxn],beg[maxn],c[maxn],w[maxn],pre[maxn],dis[maxn],vis[maxn],q[maxn<<3];
int n,e=1,m,s,t,maxflow;
inline int read()
void add(register int x,register int y,register int flow,register int cost)
int spfa()}}
}return !(dis[t]==inf);
}int mcmf()
maxflow+=d;
}return cost;
}int main()
int mincost=mcmf();
printf("%d %d\n",maxflow,mincost);
return 0;
}
網路流總結
今天學的網路流,總的感覺來說稍難,不管是理解還是什麼,但是理解了後,就變得簡單許多。ford fulkerson演算法 是來求最大流量問題,從源點出發,到匯點,到底能多少能流入匯點。演算法 1 從源點出發,找相鄰邊,如果相鄰邊未被找過並且還可以流入流量就dfs。2 更新流入的邊。3 重複操作,直到沒...
網路流總結
今天做了一天的網路流,也發現了很多有趣 有毒 的建圖方法,也算是收穫很多了,這裡就做個總結吧。網路流跑的方法大家都會我就不說了,題考察的重點也就是建圖。建圖就涉及到2個方面 1.建點。建點其實就是網路流的難點了,一般點弄好了邊也容易了。建點的困難就在於有時要拆點,我總結了一下拆點主要是這幾個作用 a...
網路流總結
1.hdu1532 給網路圖,求1 n的最大流.注意邊數 2 2.hdu3572 經典建圖模型,有些東西能轉換為容量考慮 網路流演算法.dinic學了乙個多路增廣優化,能少一次遞迴的時間 1.hdu1533 建圖方式,假設有cntm個人,cnth個房子,分別對應編號 1,cntm cntm 1,cn...