吃飽了撐的去開了一下網路流從入門到入土的題單
簡單在這裡整理一下學到的建模小知識
首先先放乙個板子在這裡
#include #define int long long
#define inf 1e18
#define n 1000005
#define m 2000005
using namespace std;
int dep[n],cur[n],n,m,s,t,ans=0;
int to[m],nxt[m],head[n],cnt=1,val[m];
void add_edge(int x,int y,int z)
queueque;
bool bfs()
} if(dep[t])return 1;
return 0;
} int dfs(int nw,int sum)
if(sum == 0) return tmp;
} if(tmp==0)dep[nw]=0;
return tmp;
}int dinic()
signed main()
網路流建模中最常用的操作
用於有點權(即乙個點中不能使用多次的情況)
具體操作為把每個點拆成 \(i_x\) 和 \(i_y\) 兩個點,給 \(i_x\) 和 \(i_y\) 連一條邊權為 \(v_i\) 的邊
對於原圖上的每一條邊 \(i \rightarrow j\) , 給 \(i_y\) 和 \(j_x\) 連邊,邊權一般為 \(inf\) ,原圖有邊權限制的話就按圖上邊權來
例題很多,比如洛谷p1345(這個題是最基礎的拆點,點權都為1),洛谷p1231(這個題由於每本書只能用一次所以跑網路流要拆點)
有那麼一些圖
會給你若干個限制條件使得一些點不能同時選
經過一系列的 瞎猜 證明,一般可以發現不能同時選的點往往在某個性質上必然相異
於是就可以把它轉化成 \(n\) 分圖
然後左邊連 \(s\) 右邊連 \(t\) 跑最大流就可以了
需要注意的是大多數情況下每個點只能選一次,所以 \(n > 2\) 時要用到上面的拆點技巧(說的就是上邊的第二道例題)
例題也很多,比如洛谷p5030,洛谷p2071
這個東西和網路流相性不錯,不少網路流題的表現形式都是網格圖
基本沒什麼太多技巧,除了別忘建雙向邊之外也不太容易錯
提到這個的主要原因是在網格圖上dinic的複雜度超級優秀,可以跑 \(n=1e6,m=6e6\) 的情況
例題:洛谷p4001(就是這個題,有 \(1e6\) 個點網路流跑的飛快),洛谷p2598
有些喪心病狂的題目會把計算幾何和網路流出到一起
所以這裡補充一點計算幾何小知識
點到直線的距離:
在直線上隨意找兩個點 \(x\) , \(y\),設原來的點為點 \(p\) ,叉乘一下向量 \(p\rightarrow x\) 和向量 \(y\rightarrow x\) ,將絕對值再除以 \(x\) 和 \(y\) 的距離就可以了
叉乘的公式 \(x_x*y_y-x_y*y_x\)
點乘的公式 \(x_x*y_x+x_y*y_y\)
例題:洛谷p4048
這是網路流中乙個非常有趣的問題
例題長成這樣:(出處:洛谷p2672)
w 教授正在為國家航天中心計畫一系列的太空飛行。每次太空飛行可進行一系列商業性實驗而獲取利潤。現已確定了乙個可供選擇的實驗集合 $ e = $,和進行這些實驗需要使用的全部儀器的集合 $ i = $。實驗 $ e_j $ 需要用到的儀器是 $ i $ 的子集 $ r_j \subseteq i $。
配置儀器 $ i_k $ 的費用為 $ c_k $ 美元。實驗 $ e_j $ 的贊助商已同意為該實驗結果支付 $ p_j $ 美元。w 教授的任務是找出乙個有效演算法,確定在一次太空飛行中要進行哪些實驗並因此而配置哪些儀器才能使太空飛行的淨收益最大。這裡淨收益是指進行實驗所獲得的全部收入與配置儀器的全部費用的差額。
對於給定的實驗和儀器配置情況,程式設計找出淨收益最大的試驗計畫。
對於這類題,我們的做法是:讓 \(s\) 與所有的正權點相連,所有的負權點與 \(t\) 相連,對於原圖中的所屬關係根據是否可以付出代價不選連一條權值為 \(inf/val\) 的邊,然後跑最小割(最大流),答案就是正權和減去最小割。
舉個例子,對於這道題,我們可以這麼畫圖
(這圖是賀的)
簡單口胡一下正確性
首先最大流等於最小割
由於中間的邊無窮大我們不需要考慮這些邊,只要考慮割掉的是實驗獎金還是儀器費用就好了
如果割掉的是實驗獎金,那麼最終的最小割裡就算入了這個實驗的獎金,等於說沒做
如果割掉的是儀器費用,那麼最終的最小割裡就算入了儀器費用,等於說購買了這些儀器
所以顯然這是可行的
最優性的話,根據上面的 感性理解 證明我們已經知道了答案是正權和減去圖的乙個割,那麼顯然最小割最優
例題:上面那道,還有洛谷p3872,洛谷p3410
這個其實應該放在前面但是沒有關係
首先最小割在數值上是等於最大流的,並且在跑最大流時可以求出最小割的一種方案
具體來說就是從 \(s\) 開始dfs,只走 \(val>0\) 的邊,所有碰到的 \(val_i=0\) 的邊就是被割掉的邊
然後我們來**一下最小割的可行邊和必需邊
最小割的可行邊 \((x,y)\)
首先顯然這得是條滿流邊,否則肯定有更優的
其次 \(x\) 在殘量網路中不連通 \(y\),否則割了這條邊也沒用
最小割的必需邊 \((x,y)\)
首先這依然得是條滿流邊
其次殘量網路中 \(s\) 與 \(x\) 連通 ,\(y\) 與 \(t\) 連通
這樣的話如果不割這條邊 \(s\) 與 \(t\) 就連通了,所以必須割這一條
快速判斷每條邊是否是可行邊或者必需邊
我們可以先跑一遍dinic,再求一遍強聯通分量(只能走殘量網路)
對於可行邊,兩個端點不在同乙個強聯通分量內即可
對於必需邊,兩個端點分別和 \(s\) 或 \(t\) 在同乙個強聯通分量內即可
(當然都要滿足滿流條件哦)
簡單解釋一下,首先對於一條滿流邊 \((x,y)\) ,殘量網路上必然有邊 \((y,x)\) (網路流的反向邊)
因此如果 \(x\) 可以到 \(y\) ,那麼必然形成乙個環,因此對於一條滿流邊,兩個端點不在同乙個強聯通分量內是可行邊的充要條件
而如果兩個端點分別和 \(s\) 或 \(t\) 在同乙個強聯通分量內,就相當於殘量網路中兩個端點分別於 \(s\) , \(t\) 連通
所以這是必需邊的充要條件
例題:洛谷p4126
網路流 最大流最小割
網路流黃頁 最大流是增廣思想的傑作,針對增光特點,採用dinic阻塞流分層 除錯編譯通過 這個沒什麼,肯定不會考裸,模板的構建是最重要的 並且還有最小割最大流定理 相等 利用拆點實現割集劃分即選與不選,放a或b1 include2 include3 include4 include5 include...
網路流最大流最小割演算法
最大流演算法 不得不說網路流演算法是很讓人無語的演算法,要想高效率竟然要非遞迴實現深搜,很無奈,到現在還是在低效率中掙扎!最大流演算法的證明就不說了,無非就是最大流最小割定理的推導,定理描述如下 對於任意給定的網路d v,a,c 從出發點vs到收點vt的最大流的流量必等於分割的最小截集的容量!至於截...
網路流 最小割最大流定理
有乙個與最大流關係密切的問題 最小割。就是把所有的頂點分成兩個集合s和t v s,其中源點s在集合s中,匯點t在集合t中。如果把 起點在s中,終點在t中 的邊都刪除,就無法從s到達t了。我們把這樣的集合劃分 s,t 成為s t割,它的容量定義為c s,t c u,v 其中u s,t t,即起點在s中...