LOJ6001太空飞行计划(网络流24题)

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

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

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

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

样例
样例输入
2 3
10 1 2
25 2 3
5 6 7
样例输出
1 2
1 2 3
17
数据范围与提示
1≤n,m≤50


建模是很好想的
集合1里面的选了集合二对应的必须选
最大权闭合子图
或者跳过这一步我们也可以直接想到最小割的做法
考虑一个实验
S向实验连收益的边,实验向设备连INF的边,设备向T连话费的边
割前面表示不进行该实验,割后面表示进行实验
那答案就=所有收益减去最小割
转化为最大权闭合子图也是一样的道理

这题的两个坑点:
①读入鬼畜,换行符是’\r’,但是你写成’\n’居然也有分
②输出方案
这里输出方案我一开始图方便直接判断S连向实验的边权是否为0,设备连向T的边权是否为0
实际上这样是错的
为什么?
我们割前面的边不一定表示流量就为0,实际上可能我们割后面的边也会使前面的流量为0
后面也是同理

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int ans; 
int n , m , S , T;
int linkk[1100] , t , dep[1100];
bool flag;
const int oo = 0x7fffffff;
struct node{
    int n , y , v;
}e[1001000];
int read()
{
    int sum = 0;char c = getchar();bool flag = true;
    while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
    while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
    if(flag)  return sum;
     else return -sum;
}  
void insert(int x,int y,int z)
{
    e[++t].y = y;e[t].n = linkk[x];e[t].v = z;linkk[x] = t;
    e[++t].y = x;e[t].n = linkk[y];e[t].v = 0;linkk[y] = t;
}
void init()
{
    t = 1;
    n = read();m = read();S = n + m + 1;T = n + m + 2;
    for(int i = 1;i <= n;++i)
    {
        int x = read();
        ans += x;
        insert(S , i + m, x);
        while(1)
        {
            char c;
            scanf("%d%c",&x,&c);
            has[i][++has[i][0]] = x;
            insert(i + m, x , oo);
            if(c == '\r'|| c == '\n') break;
        }
    }
    for(int i = 1;i <= m;++i)
    {
        int x = read();
        insert(i , T , x);
    }
    return;
}
ll dfs(int x,ll lazy)
{
    if(x == T) return lazy;
    ll nowlazy = 0;
    ll d = 0;
    for(int i = linkk[x];i&&nowlazy < lazy;i = e[i].n)
    {
        int y = e[i].y;
        if(dep[y] == dep[x] + 1 && e[i].v > 0)
            if(d = dfs(y,min(1ll*e[i].v , lazy - nowlazy)))
            {
                nowlazy += d;
                e[i].v -= d;
                e[i^1].v += d; 
            }
    }
    if(nowlazy == 0) dep[x] = -1;
    return nowlazy;
}
queue<int>q;
bool bfs()
{
    memset(dep,-1,sizeof(dep));
    dep[S] = 0;q.push(S);
    while(q.size())
    {
        int v = q.front();
        for(int i = linkk[v];i;i = e[i].n)
            if(dep[e[i].y] == -1 && e[i].v > 0) 
                dep[e[i].y] = dep[v] + 1,q.push(e[i].y);
        q.pop();
    }
    if(dep[T] == -1) return false;
    return true;
}
int main()
{
    init();
    while(bfs())
    {       
        ll d;
        while(d = dfs(S,oo)) ans -=  d;
    }

    for(int i = 1;i <= n;++i)
        if(dep[i + m] >= 0)
            printf("%d ",i);
    printf("\n");
    for(int i = 1;i <= m;++i)
        if(dep[i] >= 0)
            printf("%d ",i);
    printf("\n%lld\n",ans);
    return 0;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 适合毕业设计、课程设计作业。这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。 所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问欢迎随时与博主沟通,第一时间进行解答!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值