题目链接:点击查看

题目大意:给出n个开区间,现在要求从中选取一定数量的区间,需要满足:

  1. 对于任意点x,所选取的区间中包含点x的个数小于等于k
  2. 区间长度和最大

要求输出最长的区间长度和

题目分析:一开始建图想错了方向,陷入了思维定式中,最后是看了题解,我感觉最好的一种建图方式就是建一条直线的图,大概就是将所有区间的端点排序,依次相连流量为无穷大,花费为0的边,而题目给出的区间之间可以连流量为1,花费为区间长度的边,这样实际上就将题目转换为了:求从源点到汇点的k条互不重复的简单路径,使得权值和最大

为什么可以这样转换呢,其实网络流说到底实质上是流量的不断转移,对于这个题目而言,我们从源点只会流出大小为k的流量,因为每个区间都会限流,所以无论怎么流,都能保证满足题目中的条件1,而现在又要求区间长度和最大,那么跑最大费用最大流就是答案了,感觉很巧妙的建图方式,学到了学到了:

  1. 源点->第一个点,流量为k,花费为0
  2. 每一个点->下一个点,流量为无穷大,花费为0
  3. 区间左端点->区间右端点,流量为1,花费为区间长度
  4. 最后一个点->汇点,流量为无穷大(大于等于k皆可,因为前面有源点限流了已经),花费为0

建完图后跑最大费用最大流就好了

代码:

#include<iostream>
#include<cstdlib>
#include<string>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<climits>
#include<cmath>
#include<cctype>
#include<stack>
#include<queue>
#include<list>
#include<vector>
#include<set>
#include<map>
#include<sstream>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e3+100;//点const int M=1e4+100;//边vector<int>v;//离散化用 int get_id(int x)
{return lower_bound(v.begin(),v.end(),x)-v.begin();
}struct Node
{int l,r,len;void cal_len(){len=r-l;}void input(){scanf("%d%d",&l,&r);v.push_back(l);v.push_back(r);cal_len();}
}a[N];struct Edge
{int to,w,cost,next;
}edge[M];int head[N],cnt;void addedge(int u,int v,int w,int cost)
{edge[cnt].to=v;edge[cnt].w=w;edge[cnt].cost=cost;edge[cnt].next=head[u];head[u]=cnt++;edge[cnt].to=u;edge[cnt].w=0;edge[cnt].cost=-cost;edge[cnt].next=head[v];head[v]=cnt++;
}int d[N],incf[N],pre[N];bool vis[N];bool spfa(int s,int t)
{memset(d,0xcf,sizeof(d));memset(vis,false,sizeof(vis));memset(pre,-1,sizeof(pre));queue<int>q;q.push(s);vis[s]=true;incf[s]=inf;d[s]=0;while(!q.empty()){int u=q.front();q.pop();vis[u]=false;for(int i=head[u];i!=-1;i=edge[i].next){int v=edge[i].to;int w=edge[i].w;int cost=edge[i].cost;if(!w)continue;if(d[v]<d[u]+cost){d[v]=d[u]+cost;pre[v]=i;incf[v]=min(incf[u],w);if(!vis[v]){vis[v]=true;q.push(v);}}}}return pre[t]!=-1;
}int update(int s,int t)
{int x=t;while(x!=s){int i=pre[x];edge[i].w-=incf[t];edge[i^1].w+=incf[t];x=edge[i^1].to;}return d[t]*incf[t];
}void init()
{memset(head,-1,sizeof(head));cnt=0;
}int solve(int st,int ed)
{int ans=0;while(spfa(st,ed))ans+=update(st,ed);return ans;
}int main()
{
//  freopen("input.txt","r",stdin);
//  ios::sync_with_stdio(false);init();int n,k,st=N-1,ed=st-1;scanf("%d%d",&n,&k);for(int i=1;i<=n;i++)a[i].input();sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());addedge(st,0,k,0);addedge(v.size()-1,ed,k,0);for(int i=1;i<v.size();i++)addedge(i-1,i,inf,0);for(int i=1;i<=n;i++)addedge(get_id(a[i].l),get_id(a[i].r),1,a[i].len);printf("%d\n",solve(st,ed));return 0;
}

洛谷 - P3358 最长k可重区间集问题(最大费用最大流+思维建边)相关推荐

  1. 洛谷 - P3357 最长k可重线段集问题(最大费用最大流+思维建边+拆点)

    题目链接:点击查看 题目大意:给出n条开线段,开线段的意思就是端点的两个点属于开区间,不属于线段中,让从中选出数条线段,满足: 在x轴选取任何一个点,选取线段向x轴映射到该点的次数小于等于k 所选线段 ...

  2. P3358 最长k可重区间集问题(网络流:串联思想)

    P3358 最长k可重区间集问题 这是一个经典模型,给定n个开区间,选择一些区间使得每个位置被覆盖次数不超过k,并最大化选择的区间长度之和. 首先一个直接的想法就是每一个区间匹配了它所对应的点,但是我 ...

  3. 网络流二十四题 ————(二十一)、P3358 最长k可重区间集问题 费用流并联与串联选择

    https://www.luogu.com.cn/problem/solution/P3358 洛谷大佬们题解写的很棒,我就不献丑了. 说下我的理解吧,可以把这个限制过程当初物理中的电路并联与串联.流 ...

  4. 【刷题】LOJ 6014 「网络流 24 题」最长 k 可重区间集

    题目描述 给定实直线 \(L\) 上 \(n\) 个开区间组成的集合 \(I\) ,和一个正整数 \(k\) ,试设计一个算法,从开区间集合 \(I\) 中选取出开区间集合 \(S \subseteq ...

  5. 最长k可重区间集问题最长k可重线段集问题

    题解: 洛谷上这两题的题意都是有问题的 按照标程题意不应该是开区间而是左开右闭区间 然后连边比较巧妙 我们可以看成选k条不相交的路径,其中i-i+1中有k条边 所以建图i-i+1流量为k,权值为0 l ...

  6. 网络流24题之最长k可重区间集问题

    对于每个点向后一个点连流量为k费用为0的边 对每一区间连l到r流量为1费用为r-l的边 然后最小费用最大流,输出取反 一开始写的r-l+1错了半天... By:大奕哥 1 #include<bi ...

  7. [网络流24题] 最长k可重区间集

    对于区间 u->v ,连接边 u->v,权值为-len,容量为1,之后对每个点 i->i+1,连边 i->i+1,容量为k,权值为0,求区间最左端点到最右端点的费用流,费用相反 ...

  8. P3357 最长k可重线段集问题 网络流

    P3357 最长k可重线段集问题 题目描述 给定平面 x-O-yx−O−y 上 nn 个开线段组成的集合 II,和一个正整数 kk .试设计一个算法,从开线段集合 II 中选取出开线段集合 S\sub ...

  9. 洛谷 - P3980 [NOI2008]志愿者招募(最小费用最大流+思维建边)

    题目链接:点击查看 题目大意:现在有n天需要志愿者,每一天需要招募的人数是Ai个人,现在有m类志愿者,每类志愿者可以在[l,r]天内被招募,需要花费的代价为Ci,现在需要安排一种招募方式,可以使得总花 ...

最新文章

  1. CloudStack API编程指南
  2. 数据库综合系列 之 存储过程
  3. 记一次线上Java程序导致服务器CPU占用率过高的问题排除过程
  4. THINKPAD T420(4180J4C)还是THINKPAD T420(4180PLC)好?
  5. mysql数据库 主主的搭建
  6. Strut2页面传参跳转 --Struts2
  7. 刚走上管理岗位的人要怎么做?
  8. 什么是接口?如何定义接口?如何实现接口?
  9. Character.digit()详解
  10. (二)XGBoost之DART booster
  11. iOS调用系统相机、相册里面的文字显示英文
  12. 云时代的阡陌纵横”的数据网络?
  13. 人生没有白读的书,每一本都算数~
  14. 欧拉角与旋转矩阵的转换关系
  15. jQuery的几种显示隐藏方法
  16. 2022-07-31:给出一个有n个点,m条有向边的图, 你可以施展魔法,把有向边,变成无向边, 比如A到B的有向边,权重为7。施展魔法之后,A和B通过该边到达彼此的代价都是7。 求,允许施展一次魔法
  17. 新氧科技与京东健康签订合作协议 迎来医美服务高品质上飞跃
  18. Apache Spark 3.0 GraphX编程指南
  19. 台式电脑显示无法自动修复此计算机,windows无法自动修复此计算机怎么解决
  20. 关于并发和并行,Go和Erlang之父都弄错了?

热门文章

  1. Redis高可用方案-哨兵模式-SpringBoot整合
  2. Lambda表达式的注意事项【理解】
  3. ES6新特性之class类的基本语法
  4. 数据库-优化-案例-count()函数的优化
  5. 使用RabbitMQ实现松耦合设计
  6. Git初始化及仓库创建和操作
  7. oracle exp 二进制,Oracle备份之exp自动逻辑备份(二)
  8. linux java maven项目_Java maven项目在window下运行正常,部署到Linux环境中启动报错,是由什么引起的?...
  9. 04 数据操作 + 数据预处理【动手学深度学习v2】
  10. Allegro 光绘文件快速导入