最小割&網路流應用
重要連結
基礎部分連結 : 二分圖 & 網路流初步
zzz大佬部落格連結 : 網路流學習筆記
重點內容:最小割二元關係新解(lyd's ppt)
題目:網路流相關題目
lyd神犇課件連結 : 網路流模型設計lyd(提取碼:m5sd)
國家集訓隊2007胡伯濤論文 : 演算法合集之《最小割模型在資訊學競賽中的應用》
最詳細(也可能現在不是了)網路流建模基礎
對於網路流的基礎部分以及其在二分圖方面的應用,詳見上面的第一個連結。
先 Copy 下重點:
最小割
最大流等於最小割。
如何找到最小割的割邊?
-
從S開始沿著殘量網路BFS,把能到達的點標記上。
-
連線已標記的點和未標記的點的正向邊
如何找最小割的必須邊?
-
從S開始BFS跑殘量網路。
-
從T開始反向BFS跑殘量網路。
-
列舉從S指向T的滿流邊,這些邊即為必須邊
如何找某種情況的最小割的可行邊?
-
滿流
-
刪掉後找不到u -> v的路徑
於是:殘餘網路中tarjan跑SCC, (u, v)的u, v都在同一SCC中說明存在殘量網路u -> v的路徑 -by lyd大佬
網路流常用思想:點邊轉化思想
拆點:
把點拆成入點和出點,兩點間邊權為點權。或者拆成有兩個特殊含義的點。
拆邊:
對於邊權比較複雜的問題(比如和第幾種情況、之前選用該點次數等有關,但不管怎樣都會選最小的情況作為代價),把所有情況分解成某幾條邊上的權值和。(類似於二進位制拆分多重揹包?)
如: #6068. 「2017 山東一輪集訓 Day4」棋盤 ;還有P4307 [JSOI2009]球隊收益 / 球隊預算
注意!
-
dinic的弧優化記得加,記得初始化!!別忘了s、t的初始化!!+1
-
一定要連反向邊!!!!!
-
費用流注意一下 \(vis\) 的適用情況
以上為開頭連結部分內容。
以下為正文。
Part 1
網路流模型設計lyd(提取碼:m5sd)
(從第八頁開始,前七頁在前面有說過)
動態加點
例題:P2050 [NOI2012]美食節
題意 : n 個菜,每個菜有 \(p_i\) 個人(互不相同)選; \(m\) 位廚師, \(j\) 廚師做 \(i\) 菜的時間為 \(t_{i, j}\)
\(n <= 40; m <= 100; \sum p <= 800\)
建議先做一下簡化版:P2053 [SCOI2007]修車
利用費用提前計算等思想,我們發現 \(j\) 廚師對答案的貢獻是: \(\sum{i * t[x_i][j]}\),其中 \(x_i\) 為交付給 \(j\) 廚師的第 \(i\) 個人選擇的菜。
然後我們的思路是把每個廚師拆成 \(\sum p_i\) 個點,代表每個廚師要做的(倒數)第 \(i\) 個菜的相關費用。(這樣費用便於計算),然後再搞一搞,用最小費用最大流跑一跑。
然後複雜度會炸掉。
我們發現肯定不會每個廚師都做 \(\sum p_i\) 道菜,直觀的想法是,誰做菜快(受到眾人的青睞)就多給他一些機會。
具體來說,就是動態加點。先按照最小費用(第一次的最短路)跑他一跑,發現誰備受青睞(都選他,即他連向匯點的邊都滿流),就給他再開一個做飯的位置,給他多做一道菜的機會。然後重複。最後一直跑到最大流為 \(\sum p_i\) 為止(所有菜都做完了)。
\(Code:\)my record
平面圖與對偶圖
經典例題 : P4001 [ICPC-Beijing 2006]狼抓兔子
平面圖 :
一張無向網路,能夠在一張紙上畫出來,並且邊不交叉。
網格圖是特殊的平面圖。
一張平面圖的對偶圖
將平面圖在紙上畫出來,並且將源點與匯點用另外一條邊相連。發現一張紙被平面圖的邊分成了好幾部分。將這幾部分用帶編號的點來表示,原圖的邊(不含後來加的源點到匯點的邊)轉化成其兩側的區域點的連邊。
平面圖的最小割 等於 其對偶圖的最短路
跑從對偶圖中的 \(S'\) -> \(T'\)的路徑,發現每條路徑都將原網路分割成兩部分(即源匯分開),是一種割。因此平面圖的最小割 = 對偶圖的最短路。
這樣,\(O(n^2m)\)(假)就有望優化成 \(O(nlogn)\)(\(dijkstra\))。
\(Code:\)my record
加強 : 有向網格圖的平面圖與對偶圖
這回我們每條邊有了兩個不同的權值。其實和之前差不多,只不過當時我們理直氣壯地把每條邊直接當作兩條邊處理,這回我們要區別這兩條邊了。
通過畫圖可知,對於網格圖的對偶圖來說,(原圖中)從坐上走到右下的最小割,就相當於(對偶圖中)從坐下走到右上。那麼我們直接把所有(原圖的)邊都逆時針旋轉 \(90\) °,就是對偶圖上的邊。
具體來說,原圖中的每條邊,就相當於(對偶圖中)從它的右側穿越到它的左側。據此建圖即可。
如果有些邊根本就沒有呢?那麼就說明這些邊不用花費任何代價就可以被割斷,設定一些流量為0 的邊即可。
拓展 : 給出平面圖,求對偶圖
給出平面圖上的一些點的座標,還有連線其中某些點的邊(含邊權),求其對偶圖。
關鍵在於求出所有小區域,需要高超的計算幾何技巧。
(直接Copy)
原圖中的每條線段看做雙向向量。
• ① 任選一條未被標記的向量u→v。
• ② 找到與向量v→u逆(或順)時針方向夾角最小的向量v→w。
• ③ 如果v→w已被標記,轉到④;否則將它標記,令v=w, u=v,重複②。
• ④ 重複①~③,直至所有向量都被標記。
• 每次到達④,都會找到一個區域。通過記錄每個區域的邊,計算它的面
積正負,可以判斷它是內部區域,還是外部的無限大區域。
• 如何求與向量v→u逆時針方向夾角最小的向量?
• 兩種需要更新答案v→p的情況:
• v→p在v→u的順時針方向(vu × vp<0)
並且v→w在v→u的逆時針方向(vu × vw>0)
• v→p和v→w在v→u同側
並且v→w在v→p的順時針方向(vp × vw<0)
例題:
點被圍起來 = 點不與最外面聯通
因此建立對偶圖,暴力列舉點集,求最小割。
多源點最小割?超級源點!
建對偶圖 + (無根)最小樹形圖。
不錯的計算幾何題。
最大權閉合子圖
一張有向無環圖,點有點權(可能為負),對於邊 \((u, v)\),如果選擇 \(u\) ,就必須選擇 \(v\)。求所選的點的最大權值和。
方法
對於所有點權為正的點 \(u\),我們連\((s, u, val[u])\);對於點權為負的點 \(v\),我們連 \((v, t, -val[v])\);對於邊 \((u, v)\),我們連 \((u, v, inf)\)。求最小割,正點權和減去最小割即為答案。
對於環,需要特殊處理(如縮點等等)。
理解與證明
首先我們先選上所有正點權。為了滿足邊的要求,我們要選擇一些負點權,或者拋棄一些正點權。
建好圖後,如果我們割掉正點和 \(S\) 之間的邊,而把正點權歸為 \(T\) 那邊,則說明我們放棄了正點;如果我們割掉負點和 \(T\) 之間的邊,而把負點歸到 \(S\) 那邊,說明我們要選擇這個負點。
因此,方案為 : 從 \(S\) 開始 \(dfs\),標記能經過的點。這些能經過的點即為我們選擇的點。
最大密度子圖
一張無向圖,點有點權,邊有邊權。選出其中的一個子圖,使得 點權之和與邊權之和的比值最小(即 邊權和與點權和的比值最大)。輸出點權之和與邊權之和的比值。
前置技能:01分數規劃
二分點權與邊權的比值為 \(d\)。那麼我們的任務是最小化 \(\sum_{p}val_p - d * \sum_eval_e\),檢視是否為正。
如果我們把每條邊看作一個點,那麼我們選擇這條邊就要獲得 \(- d * val_e\) 的代價(點權);選擇一個(原圖)點,就要獲得 \(val_p\) 的代價(點權)。並且要求選擇邊就一定要選擇邊兩邊的點。
然後成功轉化為最大(小)權閉合子圖的問題。
複雜度:約\(O((n + m)^3)\)。
演算法改進
我們希望儘量少的讓複雜度與 \(m\) 相關。
考慮二分後最後選出的那個子圖(子圖上的點記作黑點),如果我們知道子圖的點是哪些,那麼我們一定會選出黑點與黑點相連的所有邊。這些邊與子圖上的點稱之為誘導子圖。答案為:
\[ans = \sum{val_p} - d * \sum{val_e} \]
\[= \sum_p{val_p} - \frac{d}{2} * ({\sum_{(p, q), p~is~black}{val_{p, q}}} - \sum_{(p, q), p~is~black, q~is~wight}val_{p, q}) \]
其中中間的那個求和式我們可以預處理出來,成為與點權有關的式子,記之為 \(sum[p]\);最右面的那個求和式即為最小割。
我們將所有點與 \(S\) 連邊\((S, p, val[p] - d / 2 * sum[p])\),(原圖中的)邊連為雙向邊 \((u, v, 1 / 2 * val_{u, v})\),然後求最小割得:\(mincut\)
至於如何處理負數流量,以及如何處理分數,下面“最小割二元關係新解”部分會有講解。
答案即為 \(mincut\)。
方案:某點如果與 \(S\) 的連邊為割邊,則該點被選。
Continued...
混合圖歐拉回路
一張圖中既有無向邊,也有有向邊,求是否有經過每條邊恰好一次的迴路。
(無向圖歐拉回路、有向圖歐拉回路可以通過度數(或入度、出度關係)來直接判斷。)
混合圖歐拉回路可以變成:是否存在一種無向邊定向方案,使得每個點的入度等於出度。
如果我們先把無向圖隨意定向,那麼會出現某些點入度出度不等的情況。(當然,如果某個點的出入度之和為奇數,則一定無方案)但是,我們可以通過對一些無向邊的方向進行反悔,來修改每個點的出入度關係。
一條無向邊被定為(u -> v),它有機會改成(v -> u),使得 u 的出入度之差減二, v 的出入度之差加二。
因此我們設 \(D[cur] = \frac{ind[cur] - outd[cur]}{2}\),並且先將無向邊 \((u, v)\) “連”(原圖中)成 \((u -> v)\),並且連一條反悔邊 \((v -> u, val = 1)\),表示反悔將使 \(D[u]--,D[v]++\)。有向邊按題意連,同時維護 \(D\)。最終如果 \(D\) 出現小數,說明無合法方案;否則 \(S ->\) 正數 \(D\),負數 \(D -> T\)(不難,好好想想)。
然後跑最大流。如果可以滿流(最大流等於所有正數節點的權值之和),那麼說明至少存在一種方案,能夠使得該圖為歐拉回路。
實際上最快的理解方式就是舉個簡單的例子,尋找正確的方法。
無源匯有上下界可行流
rt
首先把下界強行跑滿,但是可能會不符合網路流的流量守恆的性質。
根據入與出的差值,如果某個點入過多,那麼就給它找個出的機會,就是來自 \(S\) 的幫助;反之,如果出過多,就給它找到個入的機會,就是來自 \(T\) 的幫助。
因此,我們將入過多的點與 \(S\) 相連,出過多的點與 \(T\) 相連,剩餘的邊的邊權為原圖的 \(max - min\)。然後跑最大流,能滿流就說明可行。
可行的方案為跑完最大流後的(除去 \(S\) 和 \(T\))網路(加上下屆)。
無源匯有上下界最小費用可行流
由於下界是必須選的,因此下界必須的費用是一定會對答案造成貢獻的。剩下的對答案的貢獻為 : 為了流量守恆,不得不流動的流量,出現在最後的跑最大流中。因此最後我們在連向 \(S\) 或 \(T\) 時,將邊費用設定為 0.然後跑最小費用最大流,最後兩部分總和即為答案。
最小/大費用迴圈流
例題1:UVA1659 幫助小羅拉 Help Little Laura
例題2:T134939 Tree
這裡的迴圈流指的是:無源匯,容量無下界有上界,邊有費用,需要滿足流量守恆。求一股迴圈流滿足以上條件,且費用最小。
還是常見的套路(以最小費用最大流為例):首先把負邊權給強制選上(為了更優,同時避免負環),不過注意要留“後路”,即返回邊。這樣的話雖然費用盡可能的少了,但是“流量守恆”可能就不符合了。於是我們可以利用S和T調節一下,使得流量守恆,又要儘可能少地花費。這一步就是普通的MCMF了。
即:正邊 \((u, v, w, f)\) 照常連,負邊\((u, v, w, f)\) 先讓答案加上個\(w * f\),然後連邊:\((u, t, w, 0), (s, v, w, 0), (v, u, w, -f)\),跑最小費用最大流。最終答案就是一開始加的那些\(w * f\) 再加上後來跑的最小費用。
有源匯有上下界可行流
rt
實際上這個更常考些, 如: Budget 和 Shoot the Bullet
有源匯的網路流,源匯可以不滿足流量守恆,源點可以隨便流出,匯點可以隨便流入。於是我們將其連邊( \(T\) -> \(S\)),上下界設定為 \([0, +∞]\)。然後就是無源匯有上下界網路流。
有源匯有上下界最大流/最小流
其實都可以用二分來做。
最大流 : 求完可行流後,從\(s\)(原源點) 到 \(t\) (原匯點)求一遍最大流(只經過原圖的點,跑餘量網路),\(ans += mxflow\)。
最小流 : 求完可行流後,從\(t\)(原匯點) 到 \(s\) (原源點)求一遍最大流(只經過原圖的點,跑餘量網路), \(ans -= mxflow\)。(lyd說填充迴圈流,並不太懂)
有源匯有上下界最小流還有一種更簡潔的方法:可以先不 \(t\) -> \(s\),跑一個“無源匯”有上下界可行流,這時候所有迴圈流都已經填滿,然後我們再 \(t\) -> \(s\),再跑一遍“無源匯”有上下界可行流,這時 \(t\) -> \(s\) 的流就是不得不跑的最小流
習題
最小割二元關係新解
見連結。
Part 2
還是直接看論文吧(儘管看不懂)
滿流邊不一定是最小割!!
基於定義的直接應用
例題:網路戰爭
題意:給一張無向圖,邊有邊權,有源點 \(S\) 和匯點 \(T\)。最小化:
\[\frac{\sum_{e}w_e}{|C|} \]
其中 \(C\) 為使 \(S\) 與 \(T\) 分開的割集, \(e\) 為割集中的邊。
直接除法不是很好做。發現答案具有單調性。我們可以二分答案 \(d\),然後 \(che()\) 函式就是要判斷:
\[\frac{\sum_{e}w_e}{|C|} >= d \]
即
\[\sum_{e = (u, v)}{w_e - d} >= 0 \]
然後以新邊權為容量,求最小割即可。
容量為負?那選他一定更優(管他在不在割集裡面),直接把它割掉(即不加這條邊或設定其容量為0)統計答案。剩下的正權邊再跑最小割。
例題 : SP839 OPTM - Optimal Marks
版本二提交處:bzoj2400
題意:
給你一個無向圖G(V,E)。 每個頂點都有一個int範圍內的整數的標記。 不同的頂點可能有相同的標記。
對於邊(u,v),我們定義:
\[Cost(u, v)\ = mark[u] \ xor \ mark [v] \]
現在我們知道某些節點的標記了。你需要確定其他節點的標記,以使邊的總成本儘可能小。在此條件下,要求點的標記總和儘可能小。 在這兩個條件下,你可以輸出任意一種合法的方案,以及邊的總成本和最小的點權和。
自己想出來的為數不多的最小割題,儘管TLE and WA 調到飛天。。。
發現 \(xor\),並且各位之間互不干擾,因此可以針對每一個二進位制位做。
然後有點像“最大權閉合子圖”?總之就是未知的點選一或者選0,要求最終邊權和最小。
發現從已知的 1 走到 0,期間至少要經過一條對答案有貢獻的邊。或者說,我們要將點集分成兩類“塊”,1和0屬於不同的“塊”內。我們要做的是選出一些點,使得“1塊”和“0塊”不連通,並要求“邊界”最少。然後就很像最小割了。
將 \(S\) 向 "1點"連 inf 邊, "0點" 向 \(T\) 連 inf 邊,原圖中的邊為 1 邊。求最小割。然後從 \(S\) 出發dfs,遍歷到的點為我們選擇的 1 點。
為什麼這樣做點權和最小呢 ?
點權和可以拆成每一位對答案的貢獻。要求我們在做每一位時,點權和一定最小,也就是說,希望dfs到儘可能少的點。因為我們總是一遇到滿流邊就停止了,因此我們走到的是 \(S\) 所在的“最小區域”。
舉個例子:
S --(inf)--> 1 --(1)--> 2 --(1)--> 3 --(1)--> 4 --(1)--> 5 --(inf)--> T
這張圖你隨便認為最小割是哪一個,反正我們從 \(S\) 出發,只走到了 1。
Continued...