太空飞行计划问题-最大权闭合图

题目描述

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

说明

感谢@FlierKing 提供spj

  是最大权闭合图的裸题,是看了  胡伯涛《最小割模型在信息学竞赛中的应用》论文来的,上面对最大权闭合图的做法进行了证明,虽然我并没看太懂= =

  做法就是建立S向实验点连边,cap为实验奖励,仪器点向T连边,cap为仪器费用,实验-仪器连边cap为inf然后跑最小割,答案就是所有实验的奖励总和减去这个最小割就是最大的净赚钱数。

  最后输出方案的做法: 将dinic过的图从S开始dfs,能访问到的实验点就是方案中包含的实验。

  我是这么理解的,净赚费用  = 实验总奖励 -(没有做的实验 + 仪器费用) ,使得括号内的费用最小答案就会最大了,对建好的图跑最小割,如果实验点最后仍与S连接说明没有割去这个实验,但是割去了这个实验所需的所有仪器。含义就是如果做某个实验是可以赚钱的就会割去他所需的仪器,如果是赔本的就会割去这个实验,正好对应了括号内的费用!

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define inf 0x3f3f3f3f
  4 struct Edge{
  5     int v,cap,flow,next;
  6 }e[100010];
  7 int tot,first[110],S,T,N,M;
  8 int d[110],cur[110];
  9 bool vis[110],vis2[110];
 10 char tools[10000];
 11 void add(int u,int v,int cap){
 12     e[tot]=Edge{v,cap,0,first[u]};
 13     first[u]=tot++;
 14     e[tot]=Edge{u,0,0,first[v]};
 15     first[v]=tot++;
 16 }
 17 int bfs(){
 18     memset(vis,0,sizeof(vis));
 19     queue<int>q;
 20     q.push(S);
 21     vis[S]=1;
 22     d[S]=0;
 23     while(!q.empty()){
 24         int u=q.front();
 25         q.pop();
 26         for(int i=first[u];~i;i=e[i].next){
 27             if(!vis[e[i].v] && e[i].cap>e[i].flow){
 28                 d[e[i].v]=d[u]+1;
 29                 vis[e[i].v]=1;
 30                 q.push(e[i].v);
 31             }
 32         }
 33     }
 34     return vis[T];
 35 }
 36 int dfs(int u,int a){
 37     if(u==T || a==0)return a;
 38     int flow=0,f;
 39     for(int &i=cur[u];~i;i=e[i].next){
 40         if(d[e[i].v]==d[u]+1 && (f=dfs(e[i].v,min(a,e[i].cap-e[i].flow)))>0){
 41             e[i].flow+=f;
 42             e[i^1].flow-=f;
 43             flow+=f;
 44             a-=f;
 45             if(a==0)break;
 46         }
 47     }
 48     return flow;
 49 }
 50 int dinic(){
 51     int ans=0;
 52     while(bfs()){
 53         for(int i=0;i<=T;++i)cur[i]=first[i];
 54         ans+=dfs(S,inf);
 55     }
 56     return ans;
 57 }
 58 void gao(int u){
 59     vis[u]=1;
 60     for(int i=first[u];~i;i=e[i].next){
 61         if(!vis[e[i].v] && e[i].cap>e[i].flow)
 62             gao(e[i].v);
 63     }
 64 }
 65 int main(){
 66     while(scanf("%d%d",&M,&N)!=EOF){
 67         int p,u,v,s=0;
 68         S=0,T=M+N+1;
 69         tot=0,memset(first,-1,sizeof(first));
 70         for(int i=1;i<=M;++i){
 71             scanf("%d",&p);
 72             add(0,i,p);
 73             s+=p;
 74             cin.getline(tools,10000);
 75             int len=0,tool;
 76             while(sscanf(tools+len,"%d",&tool)==1){
 77                 add(i,tool+M,inf);
 78                 while(tool) tool/=10,len++;
 79                 len++;
 80             }
 81         }
 82         for(int i=1;i<=N;++i){
 83             scanf("%d",&p);
 84             add(i+M,T,p);
 85         }
 86         s=s-dinic();
 87         memset(vis,0,sizeof(vis));
 88         memset(vis2,0,sizeof(vis2));
 89         gao(S);
 90         bool head=1;
 91         for(int i=1;i<=M;++i){
 92             if(vis[i]){
 93                 if(head){
 94                     printf("%d",i);
 95                     head=0;
 96                 }
 97                 else{
 98                     printf(" %d",i);
 99                 }
100                 for(int j=first[i];~j;j=e[j].next)
101                     vis2[e[j].v-M]=1;
102             }
103         }
104         puts("");
105         head=1;
106         for(int i=1;i<=N;++i){
107             if(vis2[i]){
108                 if(head){
109                     printf("%d",i);
110                     head=0;
111                 }
112                 else printf(" %d",i);
113             }
114         }
115         puts("");
116         cout<<s<<endl;
117     }
118     return 0;
119 }

原文地址:https://www.cnblogs.com/zzqc/p/9551494.html

时间: 2024-07-29 21:12:08

太空飞行计划问题-最大权闭合图的相关文章

刷题总结——太空飞行计划(最大权闭合子图用最大流解决)

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

LuoguP2762 太空飞行计划问题(最大权闭合子图,最小割)

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

1737: 太空飞行计划问题 最大权闭合子图

1.建立两个超级点S,T. 2.对每个实验跟S链接一条容量为收入的边. 3.对每个一起跟T链接一条容量为花费的边. 4.对每个实验要用到的一起链接一条容量为无穷大的边. 链表 #include <iostream> #include <queue> #include <vector> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 101,MAX

LibreOJ #6001. 「网络流 24 题」太空飞行计划 最大权闭合图

#6001. 「网络流 24 题」太空飞行计划 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合 E={E1,E2,?,Em} E = \{ E_1, E_2, \cdots, E_m \}E={E?1??,E?2??,?,E?m??},和进行这些实验

[luoguP2762] 太空飞行计划问题(最大权闭合图—最小割—最大流)

传送门 如果将每一个实验和其所对的仪器连一条有向边,那么原图就是一个dag图(有向无环) 每一个点都有一个点权,实验为收益(正数),仪器为花费(负数). 那么接下来可以引出闭合图的概念了. 闭合图是原图的一个点集,其中这个点集中每个点的出边所指向的点依然在这个点集中,那么这个点集就是个闭合图. 比如论文中的这个图: 在图 3.1 中的网络有 9 个闭合图(含空集):∅,{3,4,5},{4,5},{5},{2,4,5},{2,5},{2,3,4,5},{1,2,4,5},{1,2,3,4,5}

[网络流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题】太空飞行计划

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

题解:线性规划与网络流24题 T2 太空飞行计划问题

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

【网络流24题----02】太空飞行计划

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