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