洛谷 P2762 太空飞行计划问题

题目背景

题目描述

W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1,I2,…In}。实验Ej需要用到的仪器是I的子集RjÍI。配置仪器Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。

对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。

输入输出格式

输入格式:
第1行有2 个正整数m和n。m是实验数,n是仪器数。接下来的m 行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。最后一行的n个数是配置每个仪器的费用。

输出格式:
第1 行是实验编号;第2行是仪器编号;最后一行是净收益。

输入输出样例

输入样例#1:
2 3
10 1 2
25 2 3
5 6 7
输出样例#1:
1 2
1 2 3
17

分析:

就是成本减最大流,直接上板子

代码:

#include<iostream>  
    #include<cstdio>  
    #include<cstring>  
    using namespace std;  
    #define inf 1<<30  
    #define M 100000  
    #define N 10000  
    #define cc(m,v) memset(m,v,sizeof(m))  

    struct node {  
        int u, v, f, next;  
    } e[M];  
    int head[N], p, lev[N], cur[N];  
    int que[M];  

    void ainit() {  
        p = 0, cc(head, -1);  
    }  

    bool bfs(int s, int t) {  
        int i, u, v, qin = 0, qout = 0;  
        cc(lev, -1), lev[s] = 0, que[qin++] = s;  
        while (qout != qin) {  
            u = que[qout++];  
            for (i = head[u]; i != -1; i = e[i].next)  
                if (e[i].f > 0 && lev[v = e[i].v] == -1) {  
                    lev[v] = lev[u] + 1, que[qin++] = v;  
                    if (v == t) return 1;  
                }  
        }  
        return 0;  
    }  

    int dinic(int s, int t) {  
        int i, f, k, u, qin;  
        int flow = 0;  
        while (bfs(s, t)) {  
            memcpy(cur, head, sizeof (head));  
            u = s, qin = 0;  
            while (1) {  
                if (u == t) {  
                    for (k = 0, f = inf; k < qin; k++)  
                        if (e[que[k]].f < f) f = e[que[i = k]].f;  
                    for (k = 0; k < qin; k++)  
                        e[que[k]].f -= f, e[que[k]^1].f += f;  
                    flow += f, u = e[que[qin = i]].u;  
                }  
                for (i = cur[u]; cur[u] != -1; i = cur[u] = e[cur[u]].next)  
                    if (e[i].f > 0 && lev[u] + 1 == lev[e[i].v]) break;  
                if (cur[u] != -1)  
                    que[qin++] = cur[u], u = e[cur[u]].v;  
                else {  
                    if (qin == 0) break;  
                    lev[u] = -1, u = e[que[--qin]].u;  
                }  
            }  
        }  
        return flow;  
    }  

    void add(int u, int v, int f) {  
        e[p].u = u, e[p].v = v, e[p].f = f, e[p].next = head[u], head[u] = p++;  
        e[p].u = v, e[p].v = u, e[p].f = 0, e[p].next = head[v], head[v] = p++;  
    }  

    int main() {  
        int n, m, i, p, u, ans, sum;  
        while (scanf("%d%d", &m, &n) != -1) {  
            ainit();  
            for (i = 1, sum = 0; i <= m; i++) {  
                scanf("%d", &p);  
                sum += p, add(0, i, p);  
                while (getchar() != '\n') {  
                    scanf("%d", &u);  
                    add(i, u + m, inf);  
                }  
            }  
            for (i = 1; i <= n; i++) {  
                scanf("%d", &u);  
                add(i + m, n + m + 1, u);  
            }  
            ans = dinic(0, n + m + 1);  
            for (i = 1; i <= m; i++) if (lev[i] != -1)  
                    printf("%d ", i);  
            printf("\n");  
            for (i = m + 1; i <= n + m; i++) if (lev[i] != -1)  
                    printf("%d ", i - m);  
            printf("\n%d\n",sum - ans);  
        }  
        return 0;  
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值