【自用】有上下界的網路流

空灰冰魂發表於2015-04-24

連結:

#include <stdio.h>
int main()
{
    puts("轉載請註明出處[vmurder]謝謝");
    puts("網址:blog.csdn.net/vmurder/article/details/45242511");
}

無源匯網路流(有向圖):

最終的最大流需要是一個迴圈體,流量在內部迴圈流動。

必須流和自由流的定義:

首先設每條邊上界為flow,下界為low,那麼就存在low的必須流和flow-low的自由流。

「無源匯」有上下界的「可行」流:

建圖:

記錄每個點的所有流入的必須流in和所有流出的必須流out。
然後新圖先設立一個超級源點和一個超級匯點,
對於每條邊,保留其自由流的容量,
對於每個點,若in-out<0,點到匯點連out-in的容量,反之源點到點連in-out的容量。

判斷:

然後跑最大流,如果源點滿流則可行。

「無源匯」有上下界的「最大」流:

首先對於一張固定了每條邊最終使用容量的圖,其最大流是可以將其拆分成的流量為1的環的數量。
如果按照常規方法在建立超級源匯以後跑完的殘量網路上跑的話,可能只能列舉有剩餘流量的點作為單次源點,這樣我們無法保證每次的增廣都使得答案更優。目前網上應該沒有相關方法,蒟蒻我在浪費了若干腦細胞後證明了我這樣弱的人並不能腦補出做法。

「有源匯」有上下界的「可行」流:

我們可以從匯點連一條下界為0,上界為inf的邊到源點,這樣就轉化成了「無源匯」有上下界的「可行」流。

「有源匯」有上下界的「最大」流:

我們先跑一遍「有源匯」有上下界的「可行」流,得到最大流為maxflow1,然後在殘量網路上刪去新源和新匯,再做一遍裸最大流,得到最大流為maxflow2,則最終答案為maxflow1+maxflow2。

「有源匯」有上下界的「最小」流:

一例錯誤的方法:

直接轉化求可行流時超級源流量和。
反例:(邊格式為起點,終點,下界,上界)
S:1, T:4
1 2 10 100
2 1 1 100
1 3 10 100
3 1 1 100
3 4 1 100
可行流答案為17,可是最小流是1。
因為可以迴圈計流使同一個流量在某條邊上流多次。

正解:

一、
記錄每個點的所有流入的必須流in和所有流出的必須流out。
然後新圖先設立一個超級源點和一個超級匯點,
對於每條邊,保留其自由流的容量,
對於每個點,若in-out<0,點到匯點連out-in的容量,反之源點到點連in-out的容量。
(完全由“「無源匯」有上下界的「可行」流”部分複製過來)
二、
超級源到超級匯跑最大流,然後在殘餘網路上從匯到源連一條容量為inf的邊
三、
此時超級源到超級匯的最大流就是原圖源到匯的最小流。

有上下界的費用流

解法:

我們做特殊處理,就是把每條邊(費用k)拆成必須流(流量a,費用k-inf)和自由流(流量b,費用k)兩條邊,
然後最後答案加上∑a*inf就好了。(注意此處inf不是真的極大值,而是賦一個很大的數就好)

原理:

費用小成這樣必須選,然後選完了肯定會虧費用,要補回來。

相關文章