【最小割】【网络流24题】【P2762】 太空飞行计划问题
Description
W 教授正在为国家航天中心计划一系列的太空飞行。每次太空飞行可进行一系列商业性实验而获取利润。现已确定了一个可供选择的实验集合E={E1,E2,…,Em},和进行这些实验需要使用的全部仪器的集合I={I1,I2,…In}。实验Ej需要用到的仪器是I的子集Rj。配置仪器Ik的费用为ck美元。实验Ej的赞助商已同意为该实验结果支付pj美元。W教授的任务是找出一个有效算法,确定在一次太空飞行中要进行哪些实验并因此而配置哪些仪器才能使太空飞行的净收益最大。这里净收益是指进行实验所获得的全部收入与配置仪器的全部费用的差额。
对于给定的实验和仪器配置情况,编程找出净收益最大的试验计划。
Limitation
\(1~\leq~n,~m~\leq~50\)
Solution
为啥题解里没人讲证明啊QAQ
简化一下题意以后,发现题意是这样的:
给定一张图,有左侧的点和右侧的点,左侧的点点权为正(对应试验),右侧的点点权为负(对应器材),如果选择了左侧的某个点就必须要选右边的一部分点。要求最大化点权和。
如果将左侧的点和右侧的点之间对应连边,如果该实验要求该器材就连一条边,那么问题就被转化为了这样一个问题:
给定一个有向图,点有点权,选择一个子图,满足子图上如果选择了一个点就必须选择它后继的所有点。最大化点权和。
这是一个经典的网络流问题,如果一个点被选择了则后继必须被选择,那么称该图是 闭合的,因此该问题叫做最大权闭合子图问题。可以使用最小割解决。
具体的建图方法为:
源点向所有正权点连结一条容量为权值的边
保留原图中所有的边,容量为正无穷
所有负权点向汇点连结一条容量为权值绝对值的边
则原图的最大权闭合子图的点权和即为所有正权点权值之和减去建出的网络流图的最小割。
以下约定源点为 \(s\),汇点为 \(t\)。
在最小割图上,如果割掉 \(s\) 和 \(u\) 之间的边,代表不选择 \(u\) 进入子图,如果割掉 \(v\) 和 \(t\) 之间的边,代表选择 \(v\) 进入子图。
求完最小割后,如果点 \(i\) 与 \(s\) 相连,那么子图上会选择点 \(i\),如果 \(i\) 与 \(t\) 相连,则不选择点 \(i\)。
考虑证明:
(部分证明内容参考CaptainChen的博客)
先证明得到的子图是闭合的:
首先考虑由于求得是最小割,一个点要么和 \(s\) 相连,要么和 \(t\) 相连,否则一定割掉它向 \(s\) 或 \(t\) 的一条边是没有意义的,因为割掉该边不会改变图的不连通性,最小割不会割掉它。
由于原图中的边全部是正无穷,最小割只会割掉源点和正权点之间或负权点和汇点之间的边。
考虑如果选择了正权点 \(u\),为了保证 \(s-t\) 不连通,必须割掉 \(u\) 所有后继中的负权点。这证明了如果选择了一个正权点那么所有的后继负权点都会被选择。
如果选择了正权点 \(u\),设 \(v\) 是 \(u\) 的后继且 \(v\) 的的权值为正,由于没有割掉 \(u\),通过 \(u-v\) 之间的正无穷边总能使得 \(s-v\) 联通,于是割掉 \(s-v\) 的边是没有意义的,最小割不会割掉这条边,这证明了如果选择了一个正权点那么该点的所有后继正权点都会被选择。
点权为 \(0\) 的情况同理。
考虑事实上选择的闭合子图的过程是不可能从一个负权点开始的,因为去掉这个负权点直接选择它的后继显然优于选择该点。于是只考虑选择正权点就可以包括所有的情况。证毕。
再证明得到的是最大权子图:
考虑如果 \(i\) 与 \(s\) 联通,那么选择 \(i\),否则不选择 \(i\)。所以最小割割掉的权值和是 不被选择的正权点权值和 + 被选择的负权点的权值的绝对值和 ,即 最小割 = \(\min\{\)没被选择的正权点权值和 + 被选择的负权点的权值的绝对值和\(\}\)
于是
\]
证毕。
于是本题只需要按照上述方法建图即可。输出方案只需要输出与 \(s\) 联通的点。
Code
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
typedef long long int ll;
namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if (front == end) return -1;
}
return *(front++);
}
}
template <typename T>
inline bool qr(T &x) {
char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if (lst == '-') x = -x;
return (ch != '\r') && (ch != '\n');
}
namespace OPT {
char buf[120];
}
template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if (x < 0) {x = -x, putchar('-');}
int top=0;
do {OPT::buf[++top] = static_cast<char>(x % 10 + '0');} while (x /= 10);
while (top) putchar(OPT::buf[top--]);
if (pt) putchar(aft);
}
const int maxn = 110;
const int INF = 10000000;
struct Edge {
int u, v, flow;
Edge *nxt, *bk;
Edge(const int _u, const int _v, const int _fl, Edge* &h) {
this->u = _u; this->v = _v; this->flow = _fl; this->nxt = h; h = this;
}
};
Edge *hd[maxn], *fir[maxn];
inline void cont(const int _u, const int _v, const int _flow) {
auto u = new Edge(_u, _v, _flow, hd[_u]), v = new Edge(_v, _u, 0, hd[_v]);
(u->bk = v)->bk = u;
}
int n, m, s, t, ans;
int MU[maxn], val[maxn], trial[maxn], tol[maxn], dist[maxn];
std::vector<int>tool[maxn];
std::queue<int>Q;
bool bfs();
int dfs(const int u, int canag);
int main() {
freopen("1.in", "r", stdin);
qr(m); qr(n);
for (int i = 1, x = 0; i <= m; ++i) {
qr(MU[i]); ans += MU[i];
bool k;
do {
k = qr(x);
tool[i].push_back(x);
x = 0;
} while (k);
trial[i] = ++t;
}
for (int i = 1; i <= n; ++i) {qr(val[i]); tol[i] = ++t;}
s = ++t; ++t;
for (int i = 1; i <= m; ++i) {
cont(s, trial[i], MU[i]);
for (auto j : tool[i]) cont(trial[i], tol[j], INF);
}
for (int i = 1; i <= n; ++i) cont(tol[i], t, val[i]);
while (bfs()) {
for (int i = 1; i <= t; ++i) fir[i] = hd[i];
ans -= dfs(s, INF);
}
for (int i = 1; i <= m; ++i) if (dist[i]) qw(i, ' ', true);
putchar('\n');
for (int i = tol[1]; i <= tol[n]; ++i) if (dist[i]) qw(i - m, ' ', true);
putchar('\n');
qw(ans, '\n', true);
return 0;
}
bool bfs() {
memset(dist, 0, sizeof dist);
Q.push(s); dist[s] = 1;
while (!Q.empty()) {
int u = Q.front(); Q.pop();
for (auto e = hd[u]; e; e = e->nxt) if (e->flow > 0) {
if (dist[e->v]) continue;
dist[e->v] = dist[u] + 1;
Q.push(e->v);
}
}
return dist[t];
}
int dfs(const int u, int canag) {
if ((u == t) || (!canag)) return canag;
int _flow = 0;
for (auto &e = fir[u]; e; e = e->nxt) if (e->flow > 0) {
int v = e->v;
if (dist[v] != (dist[u] + 1)) continue;
int f = dfs(v, std::min(canag, e->flow));
_flow += f; e->flow -= f; e->bk->flow += f;
if (!(canag -= f)) break;
}
return _flow;
}
【最小割】【网络流24题】【P2762】 太空飞行计划问题的更多相关文章
- LOJ6001 - 「网络流 24 题」太空飞行计划
原题链接 Description 有个实验和个仪器,做实验有报酬买仪器有花费.每个实验都需要一些仪器,求最大净收益(实验报酬仪器花费),并输出一组方案. Solution 实验向所需仪器连边,实验的点 ...
- LibreOJ #6001. 「网络流 24 题」太空飞行计划 最大权闭合图
#6001. 「网络流 24 题」太空飞行计划 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测 ...
- Luogu 2762 太空飞行计划 / Libre 6001 「网络流 24 题」太空飞行计划 (网络流,最大流)
Luogu 2762 太空飞行计划 / Libre 6001 「网络流 24 题」太空飞行计划 (网络流,最大流) Description W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行 ...
- 题解:线性规划与网络流24题 T2 太空飞行计划问题
太空飞行计划问题 问题描述 W教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,-,Em},和进行这些实验需要 ...
- [Cogs727] [网络流24题#2] 太空飞行计划 [网络流,最小割]
建图:源点—(w[i])—>实验—(∞)—>仪器—(cost[i])—>汇点, 如果该实验造成收益,则仪器到汇点的边在最小割中, 如果该实验造成损失,则源点到实验的边在最小割中, 故 ...
- 【刷题】LOJ 6001 「网络流 24 题」太空飞行计划
题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合 \(E = \{ E_1, E_2, \cdots, E_m ...
- LibreOJ #6001. 「网络流 24 题」太空飞行计划
\(\quad\) 与网络流有关的最值有三个:最大流,最小费用,最小割.这道题是最小割.想了好久,终于想明白最小割应该怎么用. \(\quad\) 先找出矛盾的事物.在这道题中,两件事是矛盾的:做实验 ...
- 【PowerOJ1737&网络流24题】太空飞行计划问题(最小割)
题意: 思路: #include<bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned in ...
- 网络流24题:P2762 太空飞行计划问题
P2762 太空飞行计划问题 题目背景 题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合E={E1,E2,…,E ...
- 洛谷 P2762 太空飞行计划问题 P3410 拍照【最大权闭合子图】题解+代码
洛谷 P2762 太空飞行计划问题 P3410 拍照[最大权闭合子图]题解+代码 最大权闭合子图 定义: 如果对于一个点集合,其中任何一个点都不能到达此集合以外的点,这就叫做闭合子图.每个点都有一个权 ...
随机推荐
- RabbitMQ理论部分
概念 queue 队列 exchange 交换机 bind 绑定 channel 通道 一个发送消息流程包含上述四个概念.消息经过channel传递给exc ...
- 使用socket发送http请求(get/post)
手动发送http请求 解释说明 https://blog.csdn.net/zhangliang_571/article/details/23508953 http://www.cnblogs.com ...
- Django_杂
1.url带一些GET参数"url?a=1&b=2",通过QueryDict以及其urlencode()进行处理 from django.http.request impo ...
- Daily scrum 2015.10.19
这周是我们团队项目开始的第一周.我们的团队项目是“北航社团平台”,一个致力于打造北航社团资讯整合.社团工作服务与社团商品销售的一站式网络平台. 一.会议内容 1. 总体分工,江昊同学担任项目PM,王若 ...
- python接口测试之requests库(一)
一.requests库的安装 requests库作为第三方库,需要安装 cmd模式下,运行pip install requests 二.在学习如何发送请求之前,我们先来了解一下requests库,查看 ...
- 手机端学习助手的说明书需求以及团队PM选择
1.产品的背景 课堂上知识容量大.密度高,学生不能立刻掌握所学知识点,同时,网上资料冗杂繁复,指向性不强,导致学生不能高效的学习,为了充分利用学生的课余时间,培养学生自学能力,辅助老师教学,我们小组希 ...
- 进阶系列(2)—— C#集合
一.集合介绍 集合是.NET FCL(Framework Class Library)的重要组成部分,我们平常撸C#代码时免不了和集合打交道,FCL提供了丰富易用的集合类型,给我们撸码提供了极大的便利 ...
- 浅谈对IT的认识!
我是一个从农村出来的学生,家里的情况和大多数的农村同学是一样的,家里算不上有钱,父母供我读书,也已经是做到仁至义尽了. 我现在选了,一个和计算机有关的专业---计算机应用技术.就是希望毕业后,可以找到 ...
- python learning OOP2.py
class Student(object): pass s = Student() s.name = 'Chang' # 给一个实例动态绑定一个属性 print(s.name) def set_age ...
- TensorFlow问题“Attempting to use uninitialized value”
1.出现的问题: 对已经保存好的模型,在进行重载并继续训练的过程中出现了以下问题: 2.解决办法: 在查找了相关资料后,了解到,该错误是指在从tfrecord中读取数据时一些参数未被初始化,如果直接r ...