前一篇部落格寫的是最大流。先簡要說一下思路,方便下面的講解。
最大流求解是先跑一遍bfs,把每個點定義乙個深度,跑dfs的同時連線一條反向邊方便反悔,避免不必要的時間。
現在說一下費用流。
費用流的全稱是最小費用最大流(或最大費用最大流),保證最小費用的情況下跑最大流。
最小費用?
bfs -> spfa成功解決。
我們不需要再給每個點定義深度,而是直接把費用當成邊權求一遍到原點的最短路。
但是,流量的反向邊初始值為0,費用是0嗎?
顯然不是,因為如果不需要走這條邊顯然是不需要費用的,所以正向邊+反向邊的費用為0.顯然費用為-cost。
下乙個問題,如果我們找到了最短路,如何尋找路徑把費用累加並更改流量?
spfa解決!
之後我們當前dfs的流量需要用乙個陣列存起來,而不是乙個變數。
之後就沒什麼了,不會的問我。
p3381【模板】最小費用最大流
如題,給出乙個網路圖,以及其源點和匯點,每條邊已知其最大流量和單位流量費用,求出其網路最大流和在最大流情況下的最小費用。
輸入格式:
第一行包含四個正整數n、m、s、t,分別表示點的個數、有向邊的個數、源點序號、匯點序號。
接下來m行每行包含四個正整數ui、vi、wi、fi,表示第i條有向邊從ui出發,到達vi,邊權為wi(即該邊最大流量為wi),單位流量的費用為fi。
輸出格式:
一行,包含兩個整數,依次為最大流量和在最大流量情況下的最小費用。
樣例輸入:
4 5 4 3
4 2 30 2
4 3 20 3
2 3 20 1
2 1 30 9
1 3 40 5
樣例輸出:
50 280
code:
#include#include#include#includeusing namespace std;#define n 100000
int n,m,s,t;
int f[n];
int now[n];
int head[n];
int to[n];
int val[n];
int nex[n];
int cost[n];
int idx=1;
int inq[n];
int pre[n];
int maxflow;
int ans;
int a,b,c,d;
int nowflow[n];
void addedge(int a,int b,int c,int d)
bool spfa(int s,int t)}}
}if(f[t]>=0x3f3f3f3f)
return 0;
return 1;
}void ek()
maxflow+=nowflow[t];
ans+=f[t]*nowflow[t];
}int main()
while(spfa(s,t))
ek();
printf("%d %d",maxflow,ans);
}
網路流 EK演算法
ek演算法的思路 基於貪心的思想,每次選取一條起點到終點的路徑,毋庸置疑,這條路的流量就等於這條路徑上的權值是最小值。將這條路的權值都減去流量,再將路徑的反向邊加上流量 這樣可以就給貪心一次反悔的機會 無限迴圈以上步驟,到找不到任何一條起點到終點的路,最後所有的最小值加起來就是最大流了。這只是我對e...
網路流相關 最大流和費用流的EK演算法實現
luogu p3376 最大流是網路流模型的乙個基礎問題。網路流模型就是一種特殊的有向圖。概念 對於網路流模型 g v,e v 為點集,e 為邊集 有如下性質 最大流問題,用通俗的方式解釋就是從源點s到匯點t輸送流量,詢問最多有多少流量能輸送到匯點。對於這樣的問題,我們引入一些新概念 ford fu...
網路流 費用流zkw演算法
進行spfa每次對殘餘網路求最短路,記錄前驅,然後跑這條增廣路,更新答案,直到源點和匯點不連通位置 我們可以類似dinic,在spfa求完每個點到源點的距離之後,再像dinic一樣進行增廣,這樣就能多路增廣,並且還可以加當前弧優化。include using namespace std const ...