1. 程式人生 > >[基本操作]網路流和最小割

[基本操作]網路流和最小割

CXM:網路流都是套路

 

然而我發現我並不會網路流,所以來搞一搞

應該不會放程式碼。。。有點懶

 

bzoj1066 蜥蜴

一個 $r \times c$ 的網格里,每個格有一個柱子,有些柱子上有蜥蜴,每個地方有一個跳躍半徑,每次蜥蜴從柱子上跳開的時候,他起跳點的柱子高度 -1

不能有兩個蜥蜴在同一個柱子上,柱子高度為 0 就是沒柱子了,問最多能讓多少蜥蜴跳到網格外面

 

sol:

外面建一個匯 T,源 S 向每個有蜥蜴的地方連邊,能跳到 T 的向 T 連邊,每個點向能跳到的點連邊

然後發現,只有 S 出來的邊有容量限制 1 (每個柱子上最開始只有一隻蜥蜴),其餘地方沒有容量限制,每個點的流量限制是柱子高度,於是把柱子拆成兩個點,中間連柱子高度的邊就可以了

 

bzoj1070 修車

同一時刻有 N 位車主帶著他們的愛車來到了汽車維修中心。維修中心共有 M 位技術人員,不同的技術人員對不同
的車進行維修所用的時間是不同的。現在需要安排這 M 位技術人員所維修的車及順序,使得顧客平均等待的時間最
小。 說明:顧客的等待時間是指從他把車送至維修中心到維修完畢所用的時間。

 

sol:

平均時間轉化一下就是時間和

考慮到對於每個技術人員,即時是同一個人,在不同時段用他,他需要的時間也是不同的,於是把 m 個人拆成 n*m 個人

S 向車連流量 1 費用 0

每個人向 T 連流量 1 費用 0 (同一時刻只能修一個車)

每個車向所有人連流量 1 費用為 【等待時間】的邊

考慮等待時間怎麼算,如果第 i 個人修的倒數第 k 個車是 j

那他的時間就是 $k \times time_{(i,j)}$

 

bzoj3876 支線劇情

一個有邊權的有向圖,每次你可以從 1 號點開始走,走到不能走為止,要把每條邊都至少走過一次,求走過的最小總路程

 

sol:

每條邊的費用為邊權,下界為 1,上界沒有,求一下最小費用可行流即可

 

bzoj2668 交換棋子

有一個 $n$ 行 $m$ 列的黑白棋盤,你每次可以交換兩個相鄰格子(相鄰是指有公共邊或公共頂點)中的棋子,最終達到目標狀態。要求第 $i$ 行第 $j$ 列的格子只能參與 $m_{(i,j)}$ 次交換。

 

sol:

用 $f_a$ 表示 $\lfloor \frac{m_{(i,j)}}{2} \rfloor$

用 $f_b$ 表示 $\lceil \frac{m_{(i,j)}}{2} \rceil$

因為我懶得打字

這個題裡有一個比較奇怪的東西叫做“參與交換”

如果一個棋子換到了 x 位置,之後沒動過,x 位置經歷了一次“參與交換”

如果一個棋子原來就在 x,走出去了,經歷了一次

如果穿過 x 位置,經歷了兩次

這樣的話建圖就很明顯了,可以把一個點拆成 3 個點 $(a,b,c)$

其中 $a->b$ 表示走到 x,$b -> c$ 表示從 x 走出去

一開始 S 向所有有棋子的點的 $b$ 連流量 1 費用 0,所有需要棋子的 $b$ 向 T 連流量 1 費用 0

對於每一對相鄰的點 $(x,y)$ 可以建一條 $x_c$ 向 $y_a$ 的邊 ,流量 inf 費用 0

對於一個點,如果它運出去了一個黑點,那就是 $a -> b$ 連一條 $f_b$,$b->c$ 連一條 $f_a$

對於一個點,如果它接收到了一個黑點,那就是 $a -> b$ 連一條 $f_a$,$b->c$ 連一條 $f_b$

對於一個點,如果它也沒接收也沒運,那就是 $a -> b$ 連一條 $f_a$,$b->c$ 連一條 $f_a$

 

bzoj1834 網路擴容

一個網路流的圖,你可以花 $w_i$ 的代價將第 $i$ 條邊的容量增加 1,求將最大流增加 $k$ 的最小費用

 

sol:

先做一遍最大流,把殘量網路留著

然後思考,怎麼加 $k$ 呢?顯然是搞一個新源 $S'$ ,向 $S$ 連一個容量為 $k$ 的邊

然後對於殘量網路上每條邊,新建一個跟它同向的邊,流量 inf,費用 $w_i$,跑費用流就可以了