P2762 太空飞行计划问题
经典的最大权闭合子图问题
实验有正的价值,仪器的价值为负
为了实验我们必须选择相应的仪器
所以从 S 连向实验,边权为实验的价值
实验与相应仪器之间连边,边权为 INF
仪器连向 T 边权为仪器的价格
解释:
首先最大权闭合子图就是要求在一个图中求出一个联通子图
该子图没有出边能到达非子图的其他点(闭合)
且权值最大
根据我们刚才的建图方式,S 到正权值的点连边,边权为点权,负权值点连向 T,边权为点权绝对值
点之间根据依赖关系连边,边权INF
如果我们搞一个最小割,考虑最小割的实际意义
显然只会割从 S 到实验的边和从仪器到 T 的边
如果割的是从 S 到实验的边则相当于我们放弃了此实验从而可以不选择此实验需要的仪器,要扣去实验的价值
如果割的是从仪器到 T 的边则向当于我们为了某些实验而选择了此仪器,要扣去仪器的价值
那么最大收益就是实验总价值(包括没进行的实验)减去最小割,显然减最小割是最优的方案,因为如果还有流量那么说明有实验还有仪器没得到
那么还要继续考虑放弃实验或购买仪器
最后求出最大收益还不够,还要具体到实验和仪器
发现数据其实不大
所以枚举仪器,每次把此仪器的价格调成 0,如果跑完最小割发现最终收益恰好多了此仪器的价格则说明此仪器有被选择
然后根据选择的仪器就可以知道哪些实验有被进行
因为读入十分毒瘤,所以要稍微注意一下
我读入用快读加了个特判就解决了
具体看代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
using namespace std;
typedef long long ll;
bool flag;//flag用来特判是否换行
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
if(ch=='\n') flag=;//如果有换行flag=1
return x*f;
}
const int N=4e5+,INF=1e9+;
int fir[N],from[N<<],to[N<<],val[N<<],cntt,Fir[N];
inline void add(int a,int b,int c)
{
from[++cntt]=fir[a]; fir[a]=cntt;
to[cntt]=b; val[cntt]=c;
from[++cntt]=fir[b]; fir[b]=cntt;
to[cntt]=a; val[cntt]=;
}
int n,m,S,T;
int ans;
int dep[N];
queue <int> q;
int BFS()
{
for(int i=;i<=T;i++) dep[i]=;
q.push(S); dep[S]=;
while(!q.empty())
{
int x=q.front(); q.pop();
for(int i=fir[x];i;i=from[i])
{
int &v=to[i]; if(dep[v]||!val[i]) continue;
q.push(v); dep[v]=dep[x]+;
}
}
for(int i=;i<=T;i++) Fir[i]=fir[i];
return dep[T];
}
int dfs(int x,int mif)
{
if(x==T||!mif) return mif;
int fl=,res=;
for(int i=Fir[x];i;i=from[i])
{
Fir[x]=i; int &v=to[i]; if(dep[v]!=dep[x]+) continue;
if( res=dfs(v,min(mif,val[i])) )
{
fl+=res; mif-=res;
val[i]-=res; val[i^]+=res;
if(!mif) break;
}
}
return fl;
}
int Val[N],Cst[N];//Val是实验价值,Cst是仪器花费
vector <int> ned[N];//存实验需要的仪器编号
int solve(int P)//枚举仪器求最大收益
{
memset(fir,,sizeof(fir)); cntt=;//记得初始化
int res=;
for(int i=;i<=n;i++)
{
add(S,i,Val[i]);
res+=Val[i];
int len=ned[i].size();
for(int j=;j<len;j++)
add(i,n+ned[i][j],INF);
}
for(int i=;i<=m;i++)
if(i!=P) add(n+i,T,Cst[i]);//建图不解释
while(BFS()) res-=dfs(S,INF);
return res;//返回最大收益
}
bool vis[N];//判断仪器是否购买
int main()
{
int a;
n=read(),m=read();
S=n+m+; T=n+m+;
for(int i=;i<=n;i++)
{
flag=; Val[i]=read();
while(!flag)//判断是否换行
ned[i].push_back(read());
}
for(int i=;i<=m;i++) Cst[i]=read();
ans=solve();//先求一波最大收益
for(int i=;i<=m;i++)//枚举仪器
{
int p=solve(i);
if(p-ans==Cst[i]) vis[i]=;//注意要恰好等于
}
for(int i=;i<=n;i++)//然后根据仪器求出实验是否进行
{
int P=,len=ned[i].size();
for(int j=;j<len;j++) P&=vis[ned[i][j]];
if(P) printf("%d ",i);
}
printf("\n");
for(int i=;i<=m;i++) if(vis[i]) printf("%d ",i);
printf("\n");
printf("%d",ans);
return ;
}
P2762 太空飞行计划问题的更多相关文章
- 洛谷 P2762 太空飞行计划问题 P3410 拍照【最大权闭合子图】题解+代码
洛谷 P2762 太空飞行计划问题 P3410 拍照[最大权闭合子图]题解+代码 最大权闭合子图 定义: 如果对于一个点集合,其中任何一个点都不能到达此集合以外的点,这就叫做闭合子图.每个点都有一个权 ...
- 网络流24题:P2762 太空飞行计划问题
P2762 太空飞行计划问题 题目背景 题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,E ...
- P2762 太空飞行计划问题(网络流24题之一)
题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的 ...
- P2762 太空飞行计划问题 网络流
题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的 ...
- 【luogu P2762 太空飞行计划问题】 题解
题目链接:https://www.luogu.org/problemnew/show/P2762 算是拍照那个题的加强下. 输入真的很毒瘤.(都这么说但好像我的过了?) #include <qu ...
- 洛谷 P4174 [NOI2006]最大获利 && 洛谷 P2762 太空飞行计划问题 (最大权闭合子图 && 最小割输出任意一组方案)
https://www.luogu.org/problemnew/show/P4174 最大权闭合子图的模板 每个通讯站建一个点,点权为-Pi:每个用户建一个点,点权为Ci,分别向Ai和Bi对应的点连 ...
- 洛谷 - P2762 - 太空飞行计划问题 - 最小割
https://www.luogu.org/problemnew/solution/P2762 最小割对应的点,在最后一次更新中dinic的bfs会把他的dep重置掉.所以可以根据这个性质复原最小割. ...
- P2762 太空飞行计划问题 最大权闭合子图
link:https://www.luogu.org/problemnew/show/P2762 题意 承担实验赚钱,但是要花去对应仪器的费用,仪器可能共用.求最大的收益和对应的选择方案. 思路 这道 ...
- luogu P2762 太空飞行计划问题
好像是最大权闭合图,也就是最大流最小割啦,找出最大流的路径输出,这题如何建模呢,一样的先设源点和汇点,源点向每个计划连capacity为赞助数的边,每个计划连相应装置capacity为无穷的边,每个装 ...
- 洛谷 [P2762] 太空飞行计划问题
最大权闭合子图 胡伯涛论文真是个好东西.jpg 求一个有向图的最大权闭合子图,常应用于有先决条件的最优化问题中 将所有正权点与源点相连,容量为点权; 将所有负权点与汇点相连,容量为点权的相反数; 将原 ...
随机推荐
- 在Sqlserver中使用Try Catch
创建错误日志表: CREATE TABLE ErrorLog(errNum INT,ErrSev NVARCHAR(1000),ErrState INT,ErrProc NVARCHAR(1000 ...
- Django--form基础
一.Django--form功能 用户提交数据验证 生成html标签 二.基础实例 需求 利用Django的form功能,接收用户注册信息. urls.py 1 2 3 4 5 from app01 ...
- jqgrid控件列分组
<%-- builed by manage.aspx.cmt [ver:2014.48.11] at 2014/10/11 16:48:33 --%> <%@ Page Langua ...
- 编写高质量代码改善C#程序的157个建议——建议30:使用LINQ取代集合中的比较器和迭代器
建议30:使用LINQ取代集合中的比较器和迭代器 LINQ提供了类似于SQL的语法来实现遍历.筛选与投影集合的功能. static void Main(string[] args) { List< ...
- Maven 项目使用开源中国镜像
从maven中央库下载jar非常缓慢甚至有时候会下载不下来. 可以采用中国的maven镜像.目前主要是 开源中国的镜像. 找到maven配置文件setting.xml,打开 中间添加开源中国的配置: ...
- python -Tkinter 实现一个小计算器功能
文章来源:http://www.cnblogs.com/Skyyj/p/6618739.html 本代码是基于python 2.7的 如果是对于python3.X 则需要将 tkinter 改为Tk ...
- HttpWebRequest post上传文件
public static string HttpUploadFile(string url, string path) { // 设置参数 HttpWebRequest request = WebR ...
- c# 实现点击下载功能
转自百度知道 private void DownLoad(string strName, string strPath) { string fileName = strName;//客户端保存的文件名 ...
- ASP.NET jquery-1.9.1 语句
<script src="Script/jquery-1.9.1.js"></script> <script language="javas ...
- js定时更换图片
//定时更换图片: 调用:smileChange.start(); smileChange.stop(); var smileChange = { start: function () { var t ...