網路流 消圈定理

2022-01-31 19:50:15 字數 1623 閱讀 3220

如何判定在當前流量下,乙個費用流是否是最小費用流?

這個問題等同於,是否存在一種方案,在不改變總流量的情況下改變一些邊的流量,最終減小費用。網路流的消圈定理就對此作出了解答。

可行流 \(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不存在增廣路。所謂增廣路...