P4177 [CEOI2008]order 網絡流,最小割,最大權閉合子圖
阿新 • • 發佈:2019-04-12
problem pre cli www 最大 同時 oid pan org
題目鏈接 \(Click\) \(Here\)
如果沒有租用機器就是一個裸的最大權閉合子圖。現在有了租用機器應該怎麽辦呢?
單獨拆點是不行的,因為會和直接買下的情況脫離關系,租借是和連邊直接相關的,那麽就可以考慮在邊上下功夫。我們把從工程到機器的連邊從\(INF\)變成租用費用,這樣再跑最大權閉合子圖,就可以同時考慮租用費用了。如果租用費用過高就會割斷(選用)購買機器的費用,反之亦然。
#include <bits/stdc++.h> using namespace std; const int N = 2410; const int M = 4000010; const int INF = 0x3f3f3f3f; struct Graph { int cnt, head[N]; struct edge { int nxt, to, f; }e[M]; void Init () { cnt = -1; memset (head, -1, sizeof (head)); } void add_len (int u, int v, int f) { e[++cnt] = (edge) {head[u], v, f}; head[u] = cnt; e[++cnt] = (edge) {head[v], u, 0}; head[v] = cnt; } queue <int> q; int cur[N], deep[N]; bool bfs (int s, int t) { memcpy (cur, head, sizeof (head)); memset (deep, 0x3f, sizeof (deep)); deep[s] = 0; q.push (s); while (!q.empty ()) { int u = q.front (); q.pop (); for (int i = head[u]; ~i; i = e[i].nxt) { int v = e[i].to; if (deep[v] == INF && e[i].f) { deep[v] = deep[u] + 1; q.push (v); } } } return deep[t] != INF; } int dfs (int u, int t, int lim) { if (u == t || !lim) return lim; int tmp = 0, flow = 0; for (int &i = cur[u]; ~i; i = e[i].nxt) { int v = e[i].to; if (deep[v] == deep[u] + 1) { tmp = dfs (v, t, min (lim, e[i].f)); lim -= tmp; flow += tmp; e[i ^ 0].f -= tmp; e[i ^ 1].f += tmp; if (!lim) break; } } return flow; } int Dinic (int s, int t) { int min_cut = 0; while (bfs (s, t)) { min_cut += dfs (s, t, INF); } return min_cut; } }G; int n, m; int A (int x) {return n * 0 + x;} int B (int x) {return n * 1 + x;} int main () { //freopen ("data.in", "r", stdin); cin >> n >> m; G.Init (); int s = N - 1, t = N - 2, ans = 0; for (int i = 1; i <= n; ++i) { static int w, k, p, r; cin >> w >> k; ans += w; G.add_len (s, A (i), w); //get_val = w for (int j = 1; j <= k; ++j) { cin >> p >> r; G.add_len (A (i), B (p), r); //rent cost = r } } for (int i = 1; i <= m; ++i) { static int w; cin >> w; G.add_len (B (i), t, w); } cout << ans - G.Dinic (s, t) << endl; }
P4177 [CEOI2008]order 網絡流,最小割,最大權閉合子圖