luogu3358 最长k可重区间集问题 网络流
题目大意:
关键词:最小费用最大流 不相交路径
如果两个线段重叠了,那我们则把一个线段放在下一层,另一个线段放在上一层。把流量为1的流看作一条线,一条线把位于同一层的线段(互不重叠)都串了起来。最多有k层,则总流量最多为k。问题变成了:每条线如何串串出的线段的长度总和最大?
构图思路1:同一层每一线段都有可能是该层的第一个线段或是该层的最后一个线段。每个位于该线段后面的、不与该线段重合的线段,都是该线段潜在的同一层的下一个线段。因此连接s与每个区间的左端点、每个区间的右端点和T,每个区间的右端点连接每一个不与该线段重合的线段的左端点。为保证总流量最多为k,S向s连容量为k的边。每个线段费用为-线段长度。其余所有边费用0,容量1。
构图思路2:想象有一条竖直的线从左往右扫,穿线段的线也持续从左往右延伸,则竖直线割到的穿线段的线的数量就等于总流量。我们可以在下面再放一层“高速公路”,每一条线如果能在上面几层串线段就在上面几层穿线段,否则就放在“高速公路的一排车道”上往右延伸。具体做法:S点在最前,T点在最后,每个L上的点向其右面的相邻点连一条容量k费用0的边,两个点如果是线段的端点,则连一条容量1,费用-长度的边。
思路2代码:
#include <cstdio>
#include <cstring>
#include <set>
#include <queue>
#include <cmath>
#include <map>
#include <algorithm>
#include <cassert>
using namespace std; #define LOOP(i,n) for(int i=1; i<=n; i++)
const int MAX_RANGE=, MAX_NODE = MAX_RANGE*, MAX_EDGE = MAX_NODE * MAX_NODE, INF = 0x3f3f3f3f; struct MCMF
{
struct Node;
struct Edge; struct Node
{
Edge *Head, *Prev;
int Dist, Id;
bool Inq;
}; struct Edge
{
int Cap, Cost, OrgCap;
Node *From, *To;
Edge *Next, *Rev;
Edge(int cap, int cost, Node *from, Node *to, Edge *next) :Cap(cap), OrgCap(cap), Cost(cost), From(from), To(to), Next(next) {}
}; Node _nodes[MAX_NODE];
Edge *_edges[MAX_EDGE];
int _vCount, _eCount;
Node *Start, *Sink;
int TotFlow, TotCost; void Init(int n, int sId, int tId)
{
_vCount = n;
_eCount = ;
Start = &_nodes[sId], Sink = &_nodes[tId];
TotFlow = TotCost = ;
} Edge* AddEdge(Node *from, Node *to, int cap, int cost)
{
Edge *e = _edges[++_eCount] = new Edge(cap, cost, from, to, from->Head);
e->From->Head = e;
return e;
} void Build(int uId, int vId, int cap, int cost)
{
Node *u = uId + _nodes, *v = vId + _nodes;
u->Id = uId;
v->Id = vId;
Edge *edge1 = AddEdge(u, v, cap, cost), *edge2 = AddEdge(v, u, , -cost);
edge1->Rev = edge2;
edge2->Rev = edge1;
} bool SPFA()
{
queue<Node*> q;
LOOP(i, _vCount)
{
_nodes[i].Prev = NULL;
_nodes[i].Dist = INF;
_nodes[i].Inq = false;
}
Start->Dist = ;
q.push(Start);
while (!q.empty())
{
Node *u = q.front();
q.pop();
u->Inq = false;
for (Edge *e = u->Head; e; e = e->Next)
{
if (e->Cap && u->Dist + e->Cost < e->To->Dist)
{
e->To->Dist = u->Dist + e->Cost;
e->To->Prev = e;
if (!e->To->Inq)
{
e->To->Inq = true;
q.push(e->To);
}
}
}
}
return Sink->Prev;
} void Proceed()
{
while (SPFA())
{
assert(Sink->Dist != INF);
int minFlow = INF;
for (Edge *e = Sink->Prev; e; e = e->From->Prev)
minFlow = min(minFlow, e->Cap);
TotFlow += minFlow;
for (Edge *e = Sink->Prev; e; e = e->From->Prev)
{
e->Cap -= minFlow;
e->Rev->Cap += minFlow;
TotCost += minFlow * e->Cost;
}
}
}
}g; int main()
{
#ifdef _DEBUG
freopen("c:\\noi\\source\\input.txt", "r", stdin);
#endif
int totRange, totLayer, left[MAX_RANGE], right[MAX_RANGE],
idMatchP[MAX_NODE], sId, tId, id = ;
static map<int, int> pMatchId;
static set<int> pVis;
scanf("%d%d", &totRange, &totLayer);
memset(idMatchP, , sizeof(idMatchP));
memset(left, , sizeof(left));
memset(right, , sizeof(right));
LOOP(i, totRange)
{
scanf("%d%d", &left[i], &right[i]);
if (!pVis.count(left[i]))
{
idMatchP[++id] = left[i];
pVis.insert(left[i]);
}
if (!pVis.count(right[i]))
{
idMatchP[++id] = right[i];
pVis.insert(right[i]);
}
}
sId = id + ;
tId = id + ;
g.Init(tId, sId, tId);
sort(idMatchP + , idMatchP + id + );
LOOP(i, id)
pMatchId.insert(pair<int, int>(idMatchP[i], i));
LOOP(i, totRange)
g.Build(pMatchId[left[i]], pMatchId[right[i]], , left[i] - right[i]);
for (int i = ; i < id; i++)
g.Build(i, i + , totLayer, );
g.Build(sId, , totLayer, );
g.Build(id, tId, totLayer, );
g.Proceed();
printf("%d\n", -g.TotCost);
return ;
}
反思:做网络流的题时,网络流的含义应当清楚。思路多点“广度搜索”。
luogu3358 最长k可重区间集问题 网络流的更多相关文章
- COGS743. [网络流24题] 最长k可重区间集
743. [网络流24题] 最长k可重区间集 ★★★ 输入文件:interv.in 输出文件:interv.out 简单对比时间限制:1 s 内存限制:128 MB «问题描述: «编 ...
- 【网络流24题】No.21 (最长 k 可重区间集问题 最长不相交路径 最大费用流)
[] 输入文件示例input.txt4 21 76 87 109 13 输出文件示例output.txt15 [分析] 直接co题解好了,写得挺全.. [建模方法] 方法1 按左端点排序所有区间,把每 ...
- (luogu P3358)最长k可重区间集问题 [TPLY]
最长k可重区间集问题 题目链接 https://www.luogu.org/problemnew/show/3358 做法 所有点向下一个点连容量为k费用为0的边 l和r连容量为1费用为区间长度的边 ...
- 【网络流24题】最长k可重区间集(费用流)
[网络流24题]最长k可重区间集(费用流) 题面 Cogs Loj 洛谷 题解 首先注意一下 这道题目里面 在Cogs上直接做就行了 洛谷和Loj上需要判断数据合法,如果\(l>r\)就要交换\ ...
- 【网络流24题21】最长k可重区间集问题
题面戳我 题目描述 对于给定的开区间集合I和正整数k,计算开区间集合I的最长k可重区间集的长度. 输入格式: 的第 1 行有 2 个正整数n和k,分别表示开区间的个数和开区间的可重迭数.接下来的 n行 ...
- 网络流 P3358 最长k可重区间集问题
P3358 最长k可重区间集问题 题目描述 对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度. 输入输出格式 输入格式: 的第 1 行有 2 个正整数 n和 k, ...
- LibreOJ #6014. 「网络流 24 题」最长 k 可重区间集
#6014. 「网络流 24 题」最长 k 可重区间集 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 ...
- 【刷题】LOJ 6014 「网络流 24 题」最长 k 可重区间集
题目描述 给定实直线 \(L\) 上 \(n\) 个开区间组成的集合 \(I\) ,和一个正整数 \(k\) ,试设计一个算法,从开区间集合 \(I\) 中选取出开区间集合 \(S \subseteq ...
- [网络流24题] 最长k可重区间集
https://www.luogu.org/problemnew/show/3358 以区间(1,5),(2,6),(7,8)为例 建模方法一: 建模方法二: 离散化区间端点 相当于找k条费用最大的不 ...
随机推荐
- 获取Google地图位置坐标并嵌入到网页
有时候做网页的时候,可能需要一个地图显示,可能会用到Google地图,所以就分享一下get到的新技能.在网上查资料的时候有这种方式 但是我没做成功,所以找了其他的方式. 首先,打开Google地图,查 ...
- xml操作-Nested exception: org.xml.sax.SAXParseException: White spaces are required between publicId and systemId. 异常处理
异常如下: org.dom4j.DocumentException: Error on line 2 of document file:///D:/workspaces/struts2/lesson0 ...
- 快速学习mybatis框架
一.介绍Mybatis(主要从以下两点进行介绍) 1.MyBatis是一个优秀的持久层框架,它对jdbc的操作数据库的过程进行封装,使开发者只需要关注 SQL 本身,而不需要花费精力去处理例如注册驱动 ...
- 3星|《IBM商业价值报告:区块链》:一些重要行业对区块链的态度和已经发生的区块链的应用
区块链项目开发指南 (区块链技术丛书) 介绍IBM的专家们调研许多重要行业与组织后总结的各行业对区块链的态度和实际的应用.看起来有点意思,不过有两个缺点: 1:这些实际已经发生的应用基本没看到相关的新 ...
- (转)Java任务调度框架Quartz入门教程指南(二) 使用job、trigger、schedule调用定时任务
http://blog.csdn.net/zixiao217/article/details/53044890 读完第一节,我们已经对Quartz有了一个大体的认识,它可以定时帮我们执行一些处理程序, ...
- php 在Linux下的安装
1.获取php源码 wget http://cn2.php.net/get/php-5.6.6.tar.gz/from/this/mirror mv mirror php-5.6.6.tar.gz t ...
- jenkins执行python脚本
参考: https://blog.csdn.net/qq_39247153/article/details/81003244 https://blog.csdn.net/huashao0602/art ...
- js的加法操作表
Number + Number -> 加法 Boolean + Number -> 加法 Boolean + Boolean -> 加法 Number + String -> ...
- EF-调用sql进行操作
一丶执行 class Program { static void Main(string[] args) { var db = new TestDBEntities(); string sql = @ ...
- enote笔记语言(4)(ver0.4)——“5w1h2k”分析法
章节:“5w1h2k”分析法 what:我想知道某个“关键词(keyword)”(即,词汇.词语,或称单词,可以是概念|专业术语|.......)的定义. why:我想分析and搞清楚弄明白“事物 ...