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

Description

$W$教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业 性实验而获取利润。现已确定了一个可供选择的实验集合$E={E_1,E_2,...,E_m}$,和进行这些实验需要使用的全部仪器的集合$I={I_1,I_2,...,I_n}$。实验$E_j$需要用到的仪器是$I$的子集$R_j\;\in\;I$。配置仪器$I_k$的费用为$c_k$美元。实验$E_j$的赞助商已同意为该实验结果支付$p_j$美元。$W$教授的任务是确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。

Input

文件第$1$行有$2$个正整数$m,n$。$m$是实验数,$n$是仪器数。

接下来的$m$行,每行是一个实验的有关数据。第一个数赞助商同意支付该实验的费用;接着是该实验需要用到的若干仪器的编号。

最后一行的$n$个数是配置每个仪器的费用。

Output

第$1$行是实验编号.

第$2$行是仪器编号.

最后一行是净收益。

Sample Input

2 3
10 1 2
25 2 3
5 6 7

Sample Output

1 2
1 2 3
17

HINT

$n,m,p_i<50$.

Solution

最大权闭合子图.

$s$向实验i连一条流量为$p_i$的边,

实验$i$向仪器$j$连一条流量为$+\infty$的边,

仪器$i$向$t$连一条流量为$c_i$的边,

最大收益=$\sum_{i=1}^{m}p_i$-最小割.

#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 105
#define M 5205
#define INF 500
using namespace std;
struct graph{
    int nxt,to,f;
}e[M];
int g[N],c[N],p[N],dep[N],n,m,s,t,sum,cnt=1;
bool b[N];
queue<int> q;
inline bool read(int &k){
    int ret=0;char c=getchar();
    while(!isdigit(c))
        c=getchar();
    while(isdigit(c)){
        ret=(ret<<1)+(ret<<3)+c-‘0‘;
        c=getchar();
    }
    k=ret;
    return c!=‘\n‘;
}
inline void addedge(int x,int y,int f){
    e[++cnt].nxt=g[x];g[x]=cnt;e[cnt].to=y;e[cnt].f=f;
}
inline void adde(int x,int y,int f){
    addedge(x,y,f);addedge(y,x,0);
}
inline bool bfs(int u){
    memset(dep,0,sizeof(dep));
    dep[u]=1;q.push(u);
    while(!q.empty()){
        u=q.front();q.pop();
        for(int i=g[u];i;i=e[i].nxt)
            if(e[i].f>0&&!dep[e[i].to]){
                q.push(e[i].to);
                dep[e[i].to]=dep[u]+1;
            }
    }
    return dep[t];
}
inline int dfs(int u,int f){
    int ret=0;
    if(u==t) return f;
    for(int i=g[u],d;i&&f;i=e[i].nxt)
        if(e[i].f>0&&dep[e[i].to]>dep[u]){
            d=dfs(e[i].to,min(f,e[i].f));
            e[i].f-=d;e[i^1].f+=d;ret+=d;f-=d;
        }
    return ret;
}
inline int dinic(){
    int ret=0;
    while(true){
        if(!bfs(s)) return ret;
        ret+=dfs(s,INF);
    }
}
inline void Aireen(){
    scanf("%d%d",&m,&n);
    s=m+n+1;t=s+1;
    for(int i=1,k;i<=m;++i){
        if(!read(p[i])) break;
        while(read(k)) adde(i,k+m,INF);
        adde(i,k+m,INF);
    }
    for(int i=1;i<=n;++i){
        scanf("%d",&c[i]);adde(i+m,t,c[i]);
    }
    for(int i=1;i<=m;++i){
        sum+=p[i];adde(s,i,p[i]);
    }
    sum-=dinic();
    for(int i=1;i<=m;++i)
        if(!bfs(i)){
            printf("%d ",i);
            for(int j=g[i];j;j=e[j].nxt)
                b[e[j].to-m]=true;
        }
    printf("\n");
    for(int i=1;i<=n;++i)
        if(b[i]) printf("%d ",i);
    printf("\n");
    printf("%d\n",sum);
    return;
}
int main(){
    freopen("shut.in","r",stdin);
    freopen("shut.out","w",stdout);
    Aireen();
    fclose(stdin);
    fclose(stdout);
    return 0;
}
时间: 2024-10-05 02:07:45

[网络流24题]太空飞行计划问题的相关文章

[网络流24题] 太空飞行计划 (最大权闭合子图---网络最大流)

727. [网络流24题] 太空飞行计划 ★★☆ 输入文件:shuttle.in 输出文件:shuttle.out 简单对比 时间限制:1 s 内存限制:128 MB [问题描述] W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={ I1, I2,…,In }.实验Ej 需要用到的仪器是I的子集Rj∈I.配置仪器Ik 的费用为ck 美元.实验Ej

[网络流24题] 太空飞行计划(cogs 727)

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

[luogu2762] [网络流24题] 太空飞行计划问题

传送门 一道最大权闭合子图的题目.直接建图跑dinic就行了,答案为正权点-最大流. 那剩下的问题就是如果知道哪些点被选进最大权闭合子图. 我们知道一个简单割对应了一个闭合子图,当这个简单割是最小割,即最大流,其与\(s\)相关的点即为闭合子图. #include <queue> #include <cstdio> #include <cstring> #include <algorithm> #define MAXN 105 #define INF 214

网络流 24题 太空飞行问题

太空飞行计划 题目描述 输入格式 文件第1行有2个正整数m和n.m是实验数,n是仪器数.接下来的m行,每行是一个实验的有关数据.第一个数赞助商同意支付该实验的费用:接着是该实验需要用到的若干仪器的编号.最后一行的n个数是配置每个仪器的费用.(1<=n, m<=50) 输出格式 第1行是实验编号:第2行是仪器编号:最后一行是净收益. 输入样例 23 10 1 2 25 2 3 5 6 7 输出样例 2209.out 12 1 2 3 17 关于这题的吐槽:     最坑的不是构图or输出方案,这

线性规划与网络流24题第2题 太空飞行计划 最小割

/** 题目: 线性规划与网络流24题第2题 太空飞行计划 最小割 链接:http://www.cogs.pro/cogs/problem/problem.php?pid=727 题意:lv 思路:最大点权独立集(点集中任意两个点没有边相连,且点权和最大)=点权总和-最小点权覆盖集. 将实验和仪器看做节点. 实验放在二分图的左边, s->x, cap = 实验利润. 仪器放在右边, x->t, cap = 仪器费用. 如果实验u的进行需要仪器v,u->v, cap = INF. ans

【网络流24题】餐巾计划(图解)

LOJ 6008[网络流24题]餐巾计划 题解 一张图片说明建图方法: 解说: 这种建图方法完美区分开了"脏餐巾"和"干净餐巾"两种餐巾. 每天一定会有r[i]个脏餐巾,所以源点向每天的"脏餐巾"(图上used)连边,容量r[i],费用是0.另外,前一天的脏餐巾也可以留到下一天再处理,所以每天的used点向下一天的used点连一条边,容量INF,费用是0. 每天会需要r[i]个干净餐巾,所以每天的"干净餐巾"向汇点连边(图上n

【网络流24题】餐巾计划问题(最小费用最大流)

[网络流24题]餐巾计划问题(最小费用最大流) 题面 COGS 洛谷上的数据范围更大,而且要开longlong 题解 餐巾的来源分为两种: ①新买的 ②旧的拿去洗 所以,两种情况分别建图 先考虑第一种 因为新买餐巾没有任何限制,并且随时可以买 所以直接从源点向每一天连边,容量为INF,费用为餐巾的价格 因为流要流出去,所以每个点向汇点连边,容量为每天的用量,费用为0 第二种,旧的拿去洗 首先考虑一下怎么算有多少旧的餐巾 每天用旧的餐巾的数量值一定的,不可能变多 因此从源点向这些点连边,容量为每天

LOJ #6008. 「网络流 24 题」餐巾计划

#6008. 「网络流 24 题」餐巾计划 题目描述 一个餐厅在相继的 n nn 天里,每天需用的餐巾数不尽相同.假设第 i ii 天需要 ri r_ir?i?? 块餐巾.餐厅可以购买新的餐巾,每块餐巾的费用为 P PP 分:或者把旧餐巾送到快洗部,洗一块需 M MM天,其费用为 F FF 分:或者送到慢洗部,洗一块需 N NN 天,其费用为 S SS 分(S<F S < FS<F). 每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗.

「网络流24题」餐巾计划问题

题目描述 Description 一个餐厅在相继的 N 天里,每天需用的餐巾数不尽相同.假设第 i 天需要 ri块餐巾(i=1,2,…,N).餐厅可以购买新的餐巾,每块餐巾的费用为 p 分:或者把旧餐巾送到快洗部,洗一块需 m 天,其费用为 f 分:或者送到慢洗部,洗一块需 n 天(n>m),其费用为 s<f 分.每天结束时,餐厅必须决定将多少块脏的餐巾送到快洗部,多少块餐巾送到慢洗部,以及多少块保存起来延期送洗.但是每天洗好的餐巾和购买的新餐巾数之和,要满足当天的需求量.试设计一个算法为餐厅