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

题目描述

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 #include<queue>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 const int oo=0x3f3f3f3f;
  7 struct pnt{
  8     int hd;
  9     int lyr;
 10     int now;
 11 }p[10001];
 12 struct ent{
 13     int twd;
 14     int lst;
 15     int vls;
 16 }e[1000000];
 17 int cnt;
 18 int n,m;
 19 int s,t;
 20 int sum;
 21 char tmp[100000];
 22 std::queue<int>Q;
 23 void ade(int f,int t,int v)
 24 {
 25     cnt++;
 26     e[cnt].twd=t;
 27     e[cnt].vls=v;
 28     e[cnt].lst=p[f].hd;
 29     p[f].hd=cnt;
 30     return ;
 31 }
 32 bool Bfs(void)
 33 {
 34     while(!Q.empty())
 35         Q.pop();
 36     for(int i=1;i<=t;i++)
 37         p[i].lyr=0;
 38     p[s].lyr=1;
 39     Q.push(s);
 40     while(!Q.empty())
 41     {
 42         int x=Q.front();
 43         Q.pop();
 44         for(int i=p[x].hd;i;i=e[i].lst)
 45         {
 46             int to=e[i].twd;
 47             if(p[to].lyr==0&&e[i].vls>0)
 48             {
 49                 p[to].lyr=p[x].lyr+1;
 50                 if(to==t)
 51                     return true;
 52                 Q.push(to);
 53             }
 54         }
 55     }
 56     return false;
 57 }
 58 int Dfs(int x,int fll)
 59 {
 60     if(x==t)
 61         return fll;
 62     for(int& i=p[x].now;i;i=e[i].lst)
 63     {
 64         int to=e[i].twd;
 65         if(p[to].lyr==p[x].lyr+1&&e[i].vls>0)
 66         {
 67             int ans=Dfs(to,std::min(fll,e[i].vls));
 68             if(ans>0)
 69             {
 70                 e[i].vls-=ans;
 71                 e[((i-1)^1)+1].vls+=ans;
 72                 return ans;
 73             }
 74         }
 75     }
 76     return 0;
 77 }
 78 int Dinic(void)
 79 {
 80     int ans=0;
 81     while(Bfs())
 82     {
 83         int dlt;
 84         for(int i=1;i<=t;i++)
 85             p[i].now=p[i].hd;
 86         while(dlt=Dfs(s,oo))
 87             ans+=dlt;
 88     }
 89     return ans;
 90 }
 91 int main()
 92 {
 93 //    freopen("a.in","r",stdin);
 94     scanf("%d%d",&m,&n);
 95     s=n+m+1;
 96     t=s+1;
 97     for(int i=1;i<=m;i++)
 98     {
 99         int v;
100         scanf("%d",&v);
101         sum+=v;
102         ade(s,i,v);
103         ade(i,s,0);
104         int len=0;
105         memset(tmp,0,sizeof(tmp));
106         std::cin.getline(tmp,10000);
107         while(sscanf(tmp+len,"%d",&v)==1)
108         {
109             ade(i,v+m,oo);
110             ade(v+m,i,0);
111             if(v==0)len++;
112             else{
113                 while(v)
114                 {
115                     len++;
116                     v/=10;
117                 }
118             }
119             len++;
120         }
121     }
122     for(int i=1;i<=n;i++)
123     {
124         int v;
125         scanf("%d",&v);
126         ade(i+m,t,v);
127         ade(t,i+m,0);
128     }
129     int ans=Dinic();
130     for(int i=1;i<=m;i++)
131     {
132         if(p[i].lyr>1)
133             printf("%d ",i);
134     }
135     puts("");
136     for(int i=1;i<=n;i++)
137     {
138         if(p[i+m].lyr>1)
139             printf("%d ",i);
140     }
141     puts("");
142     printf("%d\n",sum-ans);
143     return 0;
144 }

原文地址:https://www.cnblogs.com/blog-Dr-J/p/10205541.html

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

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

bzoj 1497 [NOI2006]最大获利【最大权闭合子图+最小割】

不要被5s时限和50000点数吓倒!大胆网络流!我一个5w级别的dinic只跑了1s+! 看起来没有最大权闭合子图的特征--限制,实际上还是有的. 我们需要把中转站看成负权点,把p看成点权,把客户看成正权点,把c看成点权,然后把中转站点a.b作为客户点的依赖点 s点向所有正权点连边,流量为点权:所有负权点向t连边,流量为负点权(即正数!) 对于所有有依赖关系的点,由客户点向中转站点连边,流量为inf,也就是最大权闭合子图中的向其依赖点连边 连边的意义详见:http://www.cnblogs.c

最大权闭合子图(最小割)

最大权闭合子图(最大流最小割) •参考资料 [1]最大权闭合子图 •权闭合子图 存在一个图的子图,使得子图中的所有点出度指向的点依旧在这个子图内,则此子图是闭合子图. 在这个图中有8个闭合子图:∅,{3},{4},{2,4},{3,4},{1,3,4},{2,3,4},{1,2,3,4} •最大权闭合子图 在一个图中每个点具有点权值,在他的所有闭合子途中点权之和最大的即是最大权闭合子图. •详解 最大权闭合子图 结论 最大权闭合子图权值  =  所有权值为正的权值之和  -  最大流 •步骤 建

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

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

【最大权闭合子图/最小割】BZOJ3438-小M的作物【待填】

[题目大意] 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物的种子,每种作物的种子有1个(就是可以种一棵作物)(用1...n编号),现在,第i种作物种植在A中种植可以获得ai的收益,在B中种植可以获得bi的收益,而且有m种作物组合,第i个组合中的作物共同种在A中可以获得c1i的额外收益,共同总在B中可以获得c2i的额外收益,所以,小M很快地算出了种植的最大收益. [思路] 首先,如果没有组合方案应该怎么做呢?其实非常方便. 首先建立超级源点S和超级汇点T,S

最大权闭合子图 ( 最大流最小割模型 )

引入闭合子图的概念 : 通俗点说就是选出一个图的子图,使得子图中的所有点出度指向的点依旧在这个子图内,则说明此子图是闭合子图. 最大权闭合子图 : 假设每个点具有点权值,在一个图的所有闭合子图中,点权之和最大的即是最大权闭合子图. 求取最大权闭合子图的权值之和是有一个结论的 一.先抽象出一个超级源.汇点 二.将权值为正的点和超级源点连接.容量为权值 三.将权值为负的点和超级汇点连接.容量为权值的绝对值 四.然后除了源.汇之外的点原本怎么连泽怎么连.且容量为无穷大 五.最大权闭合子图权值  =  

[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}

最大权闭合图 最小割

闭合图为原图的一个子图, 满足任意一个节点的后继仍在闭合图中. 给原图的每个点以一个点权, 权值总和最大的闭合图称为最大权闭合图. 我们考虑利用最小割求解最大权闭合图. 首先, 为了权值最大, 我们贪心地将所有点权为正的点给选上, 但是这样可能会矛盾, 因为一个点权为正的点的后继可能点权为负. 我们考虑利用最小割, 减去最小的使方案合法的花费. 建立源点 S , 与 S 相连的意义是这个点被选择, 则初始的时候, 对于点权为正的点 i , 连边 (S, i, a[i]) . 建立汇点 T , 与