• 网络流24题 P2762 太空飞行计划问题


    网络流24题 P2762 太空飞行计划问题

    思路

    问题模型:最大权闭合图

    转化模型:网络最小割

    这道题是网络流中一个比较重要的模型:最大权闭合图转最大流

    建立超级源点(S)和超级汇点(T),然后每个实验连一条从(S)到实验,流量为实验收益的边,每个仪器连一条从仪器到(T), 流量为仪器耗费的边,然后需要的仪器就连一条从实验到仪器流量为(inf)(无穷大)的边,因为实验到仪器的边的流量为正无穷,所以最小割一定不会在上面,根据最大流最小割定理,最大流就等于最小割,我们按照以上所说建图,求出最大流,之后用实验利益的总和减去最大流,得出的就是最大净收益

    最大流算法我用的是( ext{Dinic})算法,因为这样方便输出,为什么?因为如果(d[i])不为(0)就说明它一定用过,这样就能方便输出啦~

    代码

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int A = 1e5 + 11;
    const int B = 1e6 + 11;
    const int mod = 1e9 + 7;
    const int inf = 0x3f3f3f3f;
    
    inline int read() {
    	char c = getchar(); int x = 0, f = 1;
    	for ( ; !isdigit(c); c = getchar()) if(c == '-') f = -1;
    	for ( ; isdigit(c); c = getchar()) x = x * 10 + (c ^ 48);
    	return x * f;
    }
    
    int m, n, cnt, opt, S, T, ans, head[A], d[A], q[A];
    struct node { int from, to, nxt, val; } e[A];
    
    inline void add(int from, int to, int val) {
    	e[cnt].to = to;
    	e[cnt].val = val;
    	e[cnt].nxt = head[from];
    	head[from] = cnt++;
    }
    
    inline bool makelevel(int s, int t) {
    	memset(d, 0, sizeof(d));
    	memset(q, 0, sizeof(q));
    	int l = 0, r = 0;
    	d[s] = 1; q[r++] = s;
    	while (l < r) {
    		int x = q[l++];
    		if (x == t) return true;
    		for (int i = head[x]; i != -1; i = e[i].nxt) {
    			int to = e[i].to;
    			if (d[to] == 0 && e[i].val > 0) {
    				d[to] = d[x] + 1;
    				q[r++] = e[i].to;
    			}
    		}
    	}
    	return false;
    }
    
    int dfs(int x, int flow, int t) {
    	if (x == t) return flow;
    	int sum = 0;
    	for (int i = head[x]; i != -1; i = e[i].nxt) {
    		int to = e[i].to;
    		if (d[to] == d[x] + 1 && e[i].val > 0) {
    			int tmp = dfs(to, min(flow - sum, e[i].val), t);
    			e[i].val -= tmp, e[i ^ 1].val += tmp;
    			sum += tmp;
    			if (sum == flow) return sum;
    		}
    	}
    	return sum;
    }
    
    int main() {
    	memset(head, -1, sizeof(head));
    	m = read(), n = read();
    	int S = 0, T = 555;
    	int w, tot = 0, x;
    	for (int i = 1; i <= m; i++) {
    		scanf("%d", &w), tot += w;
    		add(S, i, w), add(i, S, 0);
    		while (getchar() == ' ') {
    			scanf("%d", &x);
    			add(i, x + m, inf);
    			add(x + m, i, 0);
    		}
    	}
    	for (int i = 1; i <= n; i++) {
    		x = read();
    		add(i + m, T, x), add(T, i + m, 0);
    	}
    	while (makelevel(S, T)) ans += dfs(S, inf, T);
    	ans = tot - ans;
    	for (int i = 1; i <= m; i++) if (d[i]) cout << i << ' '; puts("");
    	for (int i = 1; i <= n; i++) if (d[i + m]) cout << i << ' '; puts("");
    	cout << ans << '
    ';
    	return 0;
    }
    
  • 相关阅读:
    使用SO_REVTIMEO套接字选项为recvfrom设置超时
    使用select为描述符设置超时
    套接字超时设置方法
    使用SIGALARM为recvfrom设置超时
    使用SIGALARM为connect设置超时
    20200410 阿里巴巴Java开发手册
    20200409 Vue 视频学习【归档】
    20200319 Spring MVC 官方文档【归档】
    20200319 Spring Web MVC 2-5
    20200319 Spring Web MVC 1
  • 原文地址:https://www.cnblogs.com/loceaner/p/12310836.html
Copyright © 2020-2023  润新知