首先是網路流及最小費用最大流的兩種最基礎演算法
這兩種網路流演算法的思想核心都是尋找增廣路+沿增廣路擴充套件新流
首先是dinic 演算法
使用bfs尋找增廣路,記錄增廣路中節點層數,
而在dfs中沿著層數+1的方向不斷遞推
直到無法再找到新的增廣路為止
**
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define n 105
#define next nico
int head[n]
,to[n*n*2]
,next[n*n*2]
,dis[n*n*2]
,tot=
1,d[n]
,s=0
,t,n,m;
void
add(
int x,
int y,
int z)
intbfs()
}}return d[t];}
intdfs
(int x,
int v)
}return ans;
}int
dinic()
return ans ;
}
接下來是最小費用最大流
存圖時注意反向邊的費用是正向邊的相反數
同dinic演算法的區別在於一次只有一條增廣路,且這條增廣路是費用最短路
可以使用spfa來尋找增廣路
然而所以我採用了dijkstra
但是dijkstra不能處理負邊權,怎麼辦?
一種方法是每條邊權加上乙個足夠大的數最後再減去
但是有著溢位的風險!
另一種方法
我們採用陣列h[i]表示上一次增廣路時的最短路
w[i][j]表示連線i,j邊的權值
那麼有h[i]+w[i][j]>=h[j]
所以h[i]-h[j]+w[i][j]>=0
記儲存當前最短路的陣列為f[i]
而我們可以證明最後求出的最短路長度即為f[i]-h[i]
最後為了維護h
只需要每個h[i]+=f[i]
**
#include
#include
#include
#include
#include
#include
#define n 5003
#define next nico
using namespace std;
int head[n]
,to[n*20]
,v[n*20]
,cost[n*20]
,from[n]
,flow[n]
,next[n*20]
,f[n]
,path[n]
,tot=
1,h[n]
,n,m;
int sumflow,sumcost;
int s,t;
void
add(
int x,
int y,
int a,
int b)
struct dat
}buf;
intdijkstra()
);while
(!p.
empty()
));}
}}return f[t]
!=inf;
}void
mcmf()
for(
int i =
1; i <= n; i ++)}
}int
main()
mcmf()
;printf
("%d %d"
,sumflow,sumcost)
;}
網路流 費用流模板
中求的是最小費用最大流,求最大費用最大流只需要在設定邊權時設定為原權值的相反數,執行一次最小費用最大流,計算得出最小費用的相反數就是要求的最大費用。u x v x w x c x 分別表示 x 號邊的出發點,到達點,權值和殘量。1 intspfa 29 dis s 0 10 head tail 1 ...
網路流 費用流
這個好像不考 沒事可以騙分 費用流,顧名思義,就是有費用的流,也就是說,給乙個網路流圖中的每條弧增加乙個單位流量費用。一般來說求解的費用流都是最大流最小費用。好像沒什麼好bb的 這裡推薦使用zkw演算法求解最小費用流,看著 理解就行,應該還是很好理解的。zkw演算法在稠密圖上跑得飛快,在稀疏圖上還不...
網路流 費用流
網路流有很多種類 其中最大流 有增廣路演算法和預流推進演算法。增廣路演算法就是不斷的新增增廣路。其中的dinic演算法。會稍微提到isap演算法 poj1273 首先想到dfs一直往後延伸,然後從源點到匯點計算每條路,但是這樣只是單條路的最值,有時可能因為走一條路而間接的認定了除這條路以外的某個路通...