如何判定在當前流量下,乙個費用流是否是最小費用流?
這個問題等同於,是否存在一種方案,在不改變總流量的情況下改變一些邊的流量,最終減小費用。網路流的消圈定理就對此作出了解答。
可行流 \(f\) 是當前流量下的最小費用流 \(\leftrightarrow\) 殘餘網路不存在負環
把單點看成乙個長度為 0 的環。
設 \(f'\) 是乙個流量不變,費用更小的可行流,那麼 \(f'-f\) 的每個點都滿足流入流量都等於流出流量。這是因為 \(f,f'\) 的除源點匯點的其他點都分別滿足這個條件,而總流量不變,所以源匯的流量也平衡。
這時 \(f'-f\) 是由一些環組成的。若不存在環,那麼不可能滿足流量平衡;若除了環還存在一些鏈,那麼鏈頭和鏈尾也就不滿足要求。
由於 \(w(f'),那麼 \(w(f'-f)<0\) ,所以這些環中一定存在乙個負環。
有了這個定理,我們就能判定當前流量下費用流是否是最小費用流了——若有負環就不是,否則是。
這也給我們提供了乙個得到最小費用流的方法,即不斷在負環上增廣,直到找不到負環 。
直接做的複雜度上界為 \(o(nm^2cw)\) ,其中 \(c,w\) 分別為最大容量和最大費用,整個過程可能執行 \(mcu\) 次,一次最壞找到負環為 \(o(nm)\) 。
poj2175 學會了這個方法就很簡單了。
用spfa來判斷負環,用佇列實現 600ms 左右,換成棧變成 300ms 左右。然而dfs tle 了。講道理,棧不就是dfs嗎?!
#include#include#include#include#includeusing namespace std;
inline char nchar()
inline int read()
const int maxn=205;
const int maxe=maxn*maxn*2;
int n,m,bt[maxn],ct[maxn];
struct d
} b[maxn],c[maxn];
namespace graph e[maxe];
int h[maxn],tot=1,pre[maxn],d[maxn],cnt[maxn],que[maxe],ql,qr; // pre e
bool inq[maxn],vis[maxn];
inline int add(int x,int y,int c,int w) ;
return h[x]=tot;
} void print(int x)
puts("suboptimal");
for (int i=1;i<=n;++i)
} inline int find(int x)
inline void cancle(int s,int t)
}inq[x]=false;
} }}using graph::add;
int main()
for (int i=1;i<=m;++i)
for (int i=1;i<=n;++i) for (int j=1;j<=m;++j)
graph::cancle(s,t);
puts("optimal");
return 0;
}
網路流相關定理
相關演算法 dinic演算法 最大流 ek演算法 spfa 費用流 ek演算法 dij 費用流 預流推進 最大流 上下限網路流模型 最大權閉合子圖 最大權閉包 有向圖每個點都有乙個權值 可能含負權,不然這個這個問題就沒什麼意義了 求乙個權值和最大的閉合子圖。解法 對於負權點,往t點連乙個容量為點權絕...
網路流 費用流 最大流最小割定理
囧,今天第一天電腦競賽補課,就把最大流的bfs增廣 先流預推法 最大流最小割定理 最小費用流講完了。汗。而我,就只記住了bfs增廣和最大流最小割定理。最小費用流ms差不多明白了。所以先講講bfs增廣求最大流的演算法吧。簡單的來說,就是從s 源 開始bfs,直到到達t 匯 or不存在增廣路。所謂增廣路...
網路流 費用流 最大流最小割定理
囧,今天第一天電腦競賽補課,就把最大流的bfs增廣 先流預推法 最大流最小割定理 最小費用流講完了。汗。而我,就只記住了bfs增廣和最大流最小割定理。最小費用流ms差不多明白了。所以先講講bfs增廣求最大流的演算法吧。簡單的來說,就是從s 源 開始bfs,直到到達t 匯 or不存在增廣路。所謂增廣路...