[网络流24题] 太空飞行计划问题 (最大流->最大权闭合图)
做这道题之前建议先看这篇论文,虽然论文里很多地方用了很多术语,但hbt神犇讲得很明白
这篇题解更加偏向于感性理解
把问题放到二分图上,左侧一列点是实验,权值为$p[i]$,右侧一列点是仪器,权值为$c[i]$,左侧向右侧连接了许多条出边
如果想获得$p[i]$,需要保证i的所有出边都被选上了
按照论文里最大权闭合图的做法,实验和源点$s$相连,流量为$p[i]$,仪器和汇点$t$相连,流量为$c[i]$,实验和仪器之间的边流量为$inf$
最终的答案就是实验带来的报酬总和-这个图的最大流,即报酬总和去掉 报酬填补费用的总和 ,就是净收益
我们如何比较感性地理解它呢
求最大流的过程,可以看成用实验的钱消去仪器的钱的过程
而有一些实验可能先被遍历到,而这次实验的报酬小于所需仪器的总花费,即这次实验有点亏,但买了给其他实验用的仪器,而其他实验可以把这些钱补回来
在图上的体现就是,有其他实验的流量沿着反向边流向了这次实验
通过求最小割,我们把图分割成了两块,一块包含源点,一块包含汇点
源点指向的每个联通块中,都至少存在一个点,源点向它的流量$>0$,那么这个联通块里的实验仪器组合才是获利的
那么最终答案就是总获利-最大流,方案就是再进行一次$bfs$,$dep$有值的点,即和源点在同一联通块里的点。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N1 350
#define M1 3010
#define ll long long
#define dd double
#define inf 0x3f3f3f3f
using namespace std; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
} int n,m,nm,S,T;
int p[N1],c[N1];
struct Edge{
int head[N1],to[M1<<],nxt[M1<<],flow[M1<<],cte;
void ae(int u,int v,int F)
{
cte++; to[cte]=v; flow[cte]=F;
nxt[cte]=head[u]; head[u]=cte;
}
}e; int que[M1],hd,tl,dep[N1],cur[N1];
int bfs(Edge &E)
{
int x,j,v;
memset(dep,-,sizeof(dep)); memcpy(cur,E.head,sizeof(cur));
hd=,tl=; que[++tl]=S; dep[S]=;
while(hd<=tl)
{
x=que[hd++];
for(j=E.head[x];j;j=E.nxt[j])
{
v=E.to[j]; if(dep[v]!=-||!E.flow[j]) continue;
dep[v]=dep[x]+; que[++tl]=v;
}
}
return dep[T]!=-;
}
int dfs(Edge &E,int x,int limit)
{
int j,v,flow,ans=; if(x==T||!limit) return limit;
for(j=cur[x];j;j=E.nxt[j])
{
cur[x]=j; v=E.to[j];
if( dep[v]==dep[x]+ && (flow=dfs(E,v,min(E.flow[j],limit))) )
{
limit-=flow; ans+=flow;
E.flow[j]-=flow; E.flow[j^]+=flow;
if(!limit) break;
}
}
return ans;
}
int use[N1],de;
void Dinic()
{
int mxflow=,x,j,v,i,flag,sum=;
for(i=;i<=m;i++) sum+=p[i];
while(bfs(e)) mxflow+=dfs(e,S,inf);
bfs(e);
for(i=;i<=m;i++) if(dep[i]!=-) printf("%d ",i); puts("");
for(i=m+;i<=m+n;i++) if(dep[i]!=-) printf("%d ",i-m); puts("");
printf("%d\n",sum-mxflow);
} char str[];
int main()
{
scanf("%d%d",&m,&n);
int i,j,x,y,flag,slen; S=m+n+,T=m+n+; e.cte=;
for(i=,slen=;i<=m;i++)
{
p[i]=gint(); e.ae(S,i,p[i]), e.ae(i,S,);
memset(str,,sizeof(str)); cin.getline(str,); slen=;
while(sscanf(str+slen,"%d",&x)==)
{
e.ae(i,x+m,inf); e.ae(x+m,i,);
if(!x) slen++;
else{ while(x) x/=,slen++;}
slen++;
}
}
for(i=m+;i<=m+n;i++) c[i]=gint(), e.ae(i,T,c[i]), e.ae(T,i,);
Dinic();
return ;
}
[网络流24题] 太空飞行计划问题 (最大流->最大权闭合图)的更多相关文章
- Cogs 727. [网络流24题] 太空飞行计划(最大权闭合子图)
[网络流24题] 太空飞行计划 ★★☆ 输入文件:shuttle.in 输出文件:shuttle.out 简单对比 时间限制:1 s 内存限制:128 MB [问题描述] W 教授正在为国家航天中心计 ...
- COGS727 [网络流24题] 太空飞行计划
[问题描述] W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪 ...
- [网络流24题] 太空飞行计划(cogs 727)
[问题描述] W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,-,Em},和进行这些实验需要使用的全部仪 ...
- P2762 [网络流24题]太空飞行计划问题(最小割)
地址 最大权闭合子图裸题,不说了吧,求方案就是把s集遍历一遍. 错误记录:dfs那块忘判断残量了,11分×1. #include<cstdio> #include<iostream& ...
- LibreOJ #6008. 「网络流 24 题」餐巾计划 最小费用最大流 建图
#6008. 「网络流 24 题」餐巾计划 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 ...
- Libre 6008 「网络流 24 题」餐巾计划 (网络流,最小费用最大流)
Libre 6008 「网络流 24 题」餐巾计划 (网络流,最小费用最大流) Description 一个餐厅在相继的N天里,第i天需要Ri块餐巾(i=l,2,-,N).餐厅可以从三种途径获得餐巾. ...
- LOJ #6008. 「网络流 24 题」餐巾计划
#6008. 「网络流 24 题」餐巾计划 题目描述 一个餐厅在相继的 n nn 天里,每天需用的餐巾数不尽相同.假设第 i ii 天需要 ri r_iri 块餐巾.餐厅可以购买新的餐巾,每块餐 ...
- [luogu_P1251][LOJ#6008]「网络流 24 题」餐巾计划
[luogu_P1251][LOJ#6008]「网络流 24 题」餐巾计划 试题描述 一个餐厅在相继的 \(N\) 天里,第 \(i\) 天需要 \(R_i\) 块餐巾 \((i=l,2,-,N)\) ...
- 【hjmmm网络流24题补全计划】
本文食用方式 按ABC--分层叙述思路 可以看完一步有思路后自行思考 飞行员配对问题 题目链接 这可能是24题里最水的一道吧... 很显然分成两个集合 左外籍飞行员 右皇家飞行员 跑二分图最大匹配 输 ...
随机推荐
- Java上使用Lombok插件简化Getter、Setter方法
Maven引入依赖: <dependencies> <dependency> <groupId>org.projectlombok</groupId> ...
- LINUX内核内存屏障
================= LINUX内核内存屏障 ================= By ...
- CodeForces - 344A Magnets (模拟题)
CodeForces - 344A id=46664" style="color:blue; text-decoration:none">Magnets Time ...
- BZOJ 2631 tree 动态树(Link-Cut-Tree)
题目大意:维护一种树形数据结构.支持下面操作: 1.树上两点之间的点权值+k. 2.删除一条边.添加一条边,保证加边之后还是一棵树. 3.树上两点之间点权值*k. 4.询问树上两点时间点的权值和. 思 ...
- C++开发人脸性别识别教程(12)——加入性别识别功能
经过之前几篇博客的解说,我们已经成功搭建了MFC应用框架,并实现了主要的图像显示和人脸检測程序,在这篇博文中我们要向当中加入性别识别代码. 关于性别识别,之前已经专门拿出两篇博客的篇幅来进行解说.这里 ...
- C语言开发函数库时利用不透明指针对外隐藏结构体细节
1 模块化设计要求库接口隐藏实现细节 作为一个函数库来说,尽力降低和其调用方的耦合.是最主要的设计标准. C语言,作为经典"程序=数据结构+算法"的践行者,在实现函数库的时候,必定 ...
- Tomcat容器 web.xml具体解释
<init-param> <param-name>debug</param-name> <param-value>0</param-value&g ...
- spark 按照key 分组 然后统计每个key对应的最大、最小、平均值思路——使用groupby,或者reduceby
What you're getting back is an object which allows you to iterate over the results. You can turn the ...
- Triangle LOVE(拓扑排序)
Triangle LOVE Time Limit : 2000/1000ms (Java/Other) Memory Limit : 65536/65536K (Java/Other) Total ...
- EOJ 2822 内存显示
一个 int 类型变量或 double 类型变量在连续几个字节的内存中存放.读取数值时,当数值中包含小数点时类型为 double,否则类型为 int.将读入的数值存放在 int 类型变量或 doubl ...