POJ 3422 最小費用最大流

2022-08-18 07:15:14 字數 1872 閱讀 5224

關鍵是如何處理「只能獲取一次」的問題,為此可以為每個點建立偽點,由兩條有向邊相連。原始點到偽點連一條容量為1,權值為負分數的邊;原始點到偽點連一條容量為無窮,權值為0的邊。前者表示分數只能拿一次,後者表示第二次第三次……可以繼續走這個點,但是不拿分數。負權是因為題目要求的是「最大費用」。又因為最多走同乙個點k次,所以此處的無窮大取k就行了。

1 #include 2 #include 

3 #include 4 #include 5 #include 6 #include 7 #include

8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15

using

namespace

std;

16#define rep(i,a,n) for (int i=a;i17

#define per(i,a,n) for (int i=n-1;i>=a;i--)

18#define pb push_back

19#define mp make_pair

20#define all(x) (x).begin(),(x).end()

21#define sz(x) ((int)(x).size())

22 typedef vectorvi;

23 typedef long

long

ll;24 typedef pairpii;

25const ll mod = 1e9 + 7;26

const

int inf = 0x3f3f3f3f;27

const

double eps = 1e-10;28

const

double pi = acos(-1.0

);29

//head

3031

struct edge ;

32const

int max_v = 2e4 + 7;33

intv;

34 vectorg[max_v];

35int

h[max_v];

36int

dist[max_v];

37int

prevv[max_v], preve[max_v];

3839

void add_edge(int

from, int to, int cap, int

cost) );

41 g[to].pb(edge);42}

4344

int min_cost_flow(int s, int t, int

f)63}64

}65if (dist[t] == inf) return -1

;66 rep(v, 0, v) h[v] +=dist[v];

67int d =f;

68for (int v = t; v != s; v = prevv[v]) d =min(d, g[prevv[v]][preve[v]].cap);

69 f -=d;

70 res += d*h[t];

71for (int v = t; v != s; v =prevv[v]) 76}

77return

res;78}

7980

intn, k;

8182

int pos(int i, int

j)85

86int

main()

98 cout << - min_cost_flow(0, v - 1, k) <99return0;

100 }

poj3422 最小費用最大流

記得以前做過這樣類似的題,因為那時候求的是來回的最大值,直接使用的dp,而且對費用流並不是很清楚,然後又看到了這道題。對點進行拆分建圖,乙個點拆為兩個點a和b,在a和b之間建一條花費為輸入值容量為1的邊,然後再建一條花費為0容量為k 1的邊,對b點對於其右邊和下邊都建立一條容量為k花費為0的邊,加入...

POJ 3422 最大流最小費用

題目大意 給定一張網格圖,需要從 1,1 走到 n,n 走k條路,每次走到乙個格仔上會把它的值變為0並且加到sum上去,問sum的最大值是多少 題目解析 構圖考慮到走一次費用就變成了0,所以乙個點要拆成2的點兩個點之間有一條邊容量為1,另一條容量為k 1,費用為0 因為是最大費用,只要把所有的值變成...

poj 3422 最小費用最大流

思路 求從起點到終點走k次獲得的最大值,最小費用最大流的應用 將點權轉化為邊權,需要拆點,邊容量為1,費用為該點的點權,表示該點的權值只能獲取一次,另外,應該連一條容量為inf,費用為0的邊,因為每條邊都可以走多次。另外就是增加源點和匯點了,源點與起點連容量為k,費用為0的邊,表示可以走k次,同理終...