zoukankan      html  css  js  c++  java
  • P4177 [CEOI2008]order 网络流,最小割,最大权闭合子图

    题目链接 (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;
    }
    
    
  • 相关阅读:
    ....
    CodeForces 375A(同余)
    POJ 2377 Bad Cowtractors (最小生成树)
    POJ 1258 AgriNet (最小生成树)
    HDU 1016 Prime Ring Problem(全排列)
    HDU 4460 Friend Chains(bfs)
    POJ 2236 Wireless Network(并查集)
    POJ 2100 Graveyard Design(尺取)
    POJ 2110 Mountain Walking(二分/bfs)
    CodeForces 1059B Forgery(模拟)
  • 原文地址:https://www.cnblogs.com/maomao9173/p/10693416.html
Copyright © 2011-2022 走看看