p3381 【模板】最小費用最大流
首先呢,dijkstra演算法求費用流是不如spfa求費用流的,因為這個題目不開o2優化,就過不去....
那麼我們為什麼要用這個演算法呢?個人認為確實沒什麼用....還是用spfa或者zkw求費用流吧
總所周知,dijkstra是不能跑有負環的圖的,而我們在求最小費用流的過程中一般會存在負環(反邊的存在),因此我通過引入勢的概念,將圖的邊用 e' 代替,其中 e' = e + h[u] - h[v] ,h[i]代表i點的勢,這樣的話,將新的圖中的s-t路徑的長度減去常數h[s] - h[t] ,得到的即為原圖中對應路徑的長度,因此新圖和原圖中的最短路是一致的。
因為dijkstra只實用於無負環的圖,所以我們需要選取合適的勢,將使得新圖的每一條邊的費用 cost[e] >= 0,我們就可以用dijkstra演算法求最小費用流了。
#pragma gcc optimize(2) //o2優化,不開過不去...
#include#include#include#include#include#include#include#include#include#include #include #define bug cout << "**********" << endl
#define show(x,y) cout<<"["int h[max]; //每個結點的勢
int dis[max];
int pre_node[max], pre_edge[max]; //前驅結點和對應邊
void add(int u, int v, int flow, int cost)
); edge[v].push_back();
}void min_cost_flow(int s, int t, int& min_cost, int& max_flow)
); while (!q.empty()));}
}} if (dis[t] == inf)break; //無法增廣了
for (int i = 1;i <= n;i++) h[i] += dis[i];
int flow = tot; //求這一增廣路徑的流量
for (int i = t; i != s; i = pre_node[i])
flow = min(flow, edge[pre_node[i]][pre_edge[i]].flow);
for (int i = t; i != s; i = pre_node[i])
tot -= flow;
max_flow += flow;
min_cost += flow * h[t]; }}
int main()
int min_cost, max_flow;
min_cost_flow(s, t, min_cost, max_flow);
printf("%d %d\n", max_flow, min_cost);
} return 0;
}
網路流 費用流
這個好像不考 沒事可以騙分 費用流,顧名思義,就是有費用的流,也就是說,給乙個網路流圖中的每條弧增加乙個單位流量費用。一般來說求解的費用流都是最大流最小費用。好像沒什麼好bb的 這裡推薦使用zkw演算法求解最小費用流,看著 理解就行,應該還是很好理解的。zkw演算法在稠密圖上跑得飛快,在稀疏圖上還不...
網路流 費用流
網路流有很多種類 其中最大流 有增廣路演算法和預流推進演算法。增廣路演算法就是不斷的新增增廣路。其中的dinic演算法。會稍微提到isap演算法 poj1273 首先想到dfs一直往後延伸,然後從源點到匯點計算每條路,但是這樣只是單條路的最值,有時可能因為走一條路而間接的認定了除這條路以外的某個路通...
網路流之費用流
求費用流目前好像只有ek spfa改版,時間複雜度為o n e k 其中k為最大流值。但時間上的期望時間複雜度為 o a e k 其中a為所有頂點進佇列的平均次數,可以證明a一般小於等於2。最小費用最大流 include using namespace std const int inf 0x3f3...