luogu P3358 最长k可重区间集问题
网络流建图好难,这题居然是网络流(雾,一般分析来说,有限制的情况最大流情况可以拆点通过capacity来限制,比如只使用一次,把一个点拆成入点出点,capacity为1即可,这题是限制最大k重复,可以联想到最大流问题,设源点汇点,限制的k就是其最大的capacity,其最大流一定<=k,跑出来一定满足条件,但如何计算长度呢,就使用费用流吧,最大费用流就把边权取反即可,我们不知道输入的数据范围,只知道个数,就离散化一下,每个区间只能选一次,就对离散化后的l对r连一条capacity为1,权为-len的边,源点对1连一条capacity为k的边,n对汇点连一条capacity为k的边,因为判断是否重复是从头到尾,那么源点汇点就分别连接头尾,但是这样连图不一定保证每个点都考虑进去了,可能会出现图不连通的情况,题目是开区间,那么(i,i+1)和(i+1,i+2)一定是没有交点的,就对i与i+1连一条capacity为无穷,权为0的边,这样就能保证图连通且不会影响到答案,因为如果有断层,其会顺着往下搜索,权为0,capacity为无穷,对答案无影响
#include<bits/stdc++.h>
using namespace std;
#define lowbit(x) ((x)&(-x))
typedef long long LL; const int maxm = 5e3+;
const int INF = 0x3f3f3f3f; struct edge{
int u, v, cap, flow, cost, nex;
} edges[maxm]; struct Points{
int l, r, len;
} point[]; int head[maxm], cur[maxm], cnt, fa[], d[], n, allx[];
bool inq[]; void init() {
memset(head, -, sizeof(head));
} void add(int u, int v, int cap, int cost) {
edges[cnt] = edge{u, v, cap, , cost, head[u]};
head[u] = cnt++;
} void addedge(int u, int v, int cap, int cost) {
add(u, v, cap, cost), add(v, u, , -cost);
} bool spfa(int s, int t, int &flow, LL &cost) {
for(int i = ; i <= ((n<<)|); ++i) d[i] = INF; //init()
memset(inq, false, sizeof(inq));
d[s] = , inq[s] = true;
fa[s] = -, cur[s] = INF;
queue<int> q;
q.push(s);
while(!q.empty()) {
int u = q.front();
q.pop();
inq[u] = false;
for(int i = head[u]; i != -; i = edges[i].nex) {
edge& now = edges[i];
int v = now.v;
if(now.cap > now.flow && d[v] > d[u] + now.cost) {
d[v] = d[u] + now.cost;
fa[v] = i;
cur[v] = min(cur[u], now.cap - now.flow);
if(!inq[v]) {q.push(v); inq[v] = true;}
}
}
}
if(d[t] == INF) return false;
flow += cur[t];
cost += 1LL*d[t]*cur[t];
for(int u = t; u != s; u = edges[fa[u]].u) {
edges[fa[u]].flow += cur[t];
edges[fa[u]^].flow -= cur[t];
}
return true;
} int MincostMaxflow(int s, int t, LL &cost) {
cost = ;
int flow = ;
while(spfa(s, t, flow, cost));
return flow;
} void run_case() {
init();
int l, r, k, xcnt = ;
cin >> n >> k;
for(int i = ; i <= n; ++i) {
cin >> l >> r;
allx[++xcnt] = l, allx[++xcnt] = r, point[i] = Points{l, r, r-l};
}
sort(allx+,allx++xcnt);
int len = unique(allx+,allx++xcnt)-allx;
for(int i = ; i <= n; ++i) {
point[i].l = lower_bound(allx+,allx+len,point[i].l)-allx;
point[i].r = lower_bound(allx+,allx+len,point[i].r)-allx;
}
for(int i = ; i < len-; ++i)
addedge(i, i+, INF, );
int s = , t = len;
for(int i = ; i <= n; ++i) {
addedge(point[i].l, point[i].r, , -point[i].len);
}
addedge(s, , k, ), addedge(len-, t, k, );
LL cost = ;
MincostMaxflow(s, t, cost);
cout << -cost;
} int main() {
ios::sync_with_stdio(false), cin.tie();
run_case();
cout.flush();
return ;
}
luogu P3358 最长k可重区间集问题的更多相关文章
- (luogu P3358)最长k可重区间集问题 [TPLY]
最长k可重区间集问题 题目链接 https://www.luogu.org/problemnew/show/3358 做法 所有点向下一个点连容量为k费用为0的边 l和r连容量为1费用为区间长度的边 ...
- 网络流 P3358 最长k可重区间集问题
P3358 最长k可重区间集问题 题目描述 对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度. 输入输出格式 输入格式: 的第 1 行有 2 个正整数 n和 k, ...
- 洛谷P3358 最长k可重区间集问题(费用流)
题目描述 对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度. 输入输出格式 输入格式: 的第 1 行有 2 个正整数 n和 k,分别表示开区间的个数和开区间的可重 ...
- 【Luogu】P3358最长k可重区间集问题(费用流)
题目链接 这题费用瘤,数据貌似还是错的. 把线段抽象抽象拆成两个点,入点表示左端,出点表示右端,连上容量为1费用-长度的边. 不相交线段随便连下,源点向拆出的原点S'连费用为0容量k,然后跑费用流. ...
- P3358 最长k可重区间集问题
题目链接 \(Click\) \(Here\) 这题的写法非常巧妙. 每个位置的点向它的下一个位置连一个容量为\(INF\)的边,从区间的左端点往右端点拉一条容量为\(1\),费用为区间长度的边,从起 ...
- 洛谷P3358 最长k可重区间集问题(费用流)
传送门 因为一个zz错误调了一个早上……汇点写错了……spfa也写错了……好吧好像是两个…… 把数轴上的每一个点向它右边的点连一条边,容量为$k$,费用为$0$,然后把每一个区间的左端点向右端点连边, ...
- 洛谷 P3358 最长k可重区间集问题 【最大费用最大流】
同 poj 3680 https:www.cnblogs.com/lokiii/p/8413139.html #include<iostream> #include<cstdio&g ...
- 最长k可重区间集
P3358 最长k可重区间集问题 P3357 最长k可重线段集问题 P3356 火星探险问题 P4012 深海机器人问题 P3355 骑士共存问题 P2754 [CTSC1999]家园 题目描述 ...
- 「网络流24题」「LuoguP3358」 最长k可重区间集问题(费用流
题目描述 对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度. 输入输出格式 输入格式: 的第 1 行有 2 个正整数 n和 k,分别表示开区间的个数和开区间的可重 ...
随机推荐
- HDU 3081 Marriage Match II (二分+网络流+并查集)
注意 这题需要注意的有几点. 首先板子要快,尽量使用带当前弧优化的dinic,这样跑起来不会超时. 使用弧优化的时候,如果源点设置成0,记得将cur数组从0开始更新,因为有的板子并不是. 其次这题是多 ...
- 杭电2033 人见人爱A+B
人见人爱A+B Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Sub ...
- 软件版本 Alpha、Beta、Rc
软件版本的周期 α.β.γ 表示软件测试中的三个阶段 α :第一阶段,内部测试使用 β: 第二阶段,消除了大部分不完善的地方,仍可能存在漏洞,一般提供给特定的用户使用 γ: 第三阶段,产品成熟,个别地 ...
- Idea 隐藏不必要的文件或文件夹 eg:(.idea,.gitignore,*.iml)
在使用Idea的时候,有一些文件是不必要的,可以将他们隐藏起来 方法:打开File–>Settings–>Editor如图,在File Types 中的 Ignore files and ...
- windows之杀死端口
提示: 查询端口 查询pid 杀死任务 通过 cmd 进入控制台: 查询端口: netstat -aon|findstr 1111 查询pid下的任务: tasklist|findstr 6616 杀 ...
- 几个原生js知识
1.document.documentElement 返回根节点 html. 2.原生方法获取一个对象的某个样式的值. function getStyle(obj, attr) { if(obj.cu ...
- office365激活码序列号密钥:
亲测可用: NGCM9-FWB6X-9WKYC-GRWVD-63B3P
- Ubuntu 16.04 安装Redis服务器端
~ sudo apt-get install redis-server 安装完成后,Redis服务器会自动启动,我们检查Redis服务器程序 检查Redis服务器系统进程 ~ ps -aux|grep ...
- PAT T1009 Triple Inversions
树状数组判断三元逆序对~ #include<bits/stdc++.h> using namespace std; ; int a[maxn]; ]; long long l[maxn], ...
- python笔记心得
1.字典的映射 day=10# def get_sunday():# return 'Sunday'# def get_monday():# return 'monday'# def get_tues ...