「网络流24题」「LuoguP3358」 最长k可重区间集问题

题目描述

对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度。

输入输出格式

输入格式:

的第 1 行有 2 个正整数 n和 k,分别表示开区间的个数和开区间的可重迭数。接下来的 n行,每行有 2 个整数,表示开区间的左右端点坐标。

输出格式:

将计算出的最长 k可重区间集的长度输出

输入输出样例

输入样例#1:
复制

4 2
1 7
6 8
7 10
9 13 

输出样例#1: 复制

15

说明

对于100%的数据,1<=n<=500,1<=k<=3

题解

建图:从$S$往$L$左端点连容量为k,费用为0;

从$L$上每个点$i$往点$i+1$连容量为INF,费用为0;

从$L$右端点往$T$连容量INF,费用为0。

>然后从每个区间的左端点往右端点连边,容量为1,费用为右端点$-$左端点(这道题区间长度的定义是右端点$-$左端点

然后跑最大费用最大流就行啦~

这样跑出来的费用会尽量大,而因为S处控制了流量,最大流就是k。

答案就是费用。

然后最大费用最大流就是把费用存负,跑最小费用最大流,输出答案的时候再取反就行了。

然后这道题长度没个范围,所以还要搞个离散。

  1 /*
  2     qwerta
  3     P3358 最长k可重区间集问题
  4     Accepted
  5     100
  6     代码 C++,2.16KB
  7     提交时间 2018-10-09 18:19:08
  8     耗时/内存
  9     31ms, 936KB
 10 */
 11 #include<algorithm>
 12 #include<iostream>
 13 #include<cstring>
 14 #include<cstdio>
 15 #include<cmath>
 16 #include<queue>
 17 using namespace std;
 18 const int INF=2e9;
 19 struct emm{
 20     int e,f,v,c;
 21 }a[4003];
 22 int h[1003];
 23 int tot=1;
 24 void con(int x,int y,int v,int c)
 25 {
 26     a[++tot].f=h[x];
 27     h[x]=tot;
 28     a[tot].e=y;
 29     a[tot].v=v;
 30     a[tot].c=c;
 31     a[++tot].f=h[y];
 32     h[y]=tot;
 33     a[tot].e=x;
 34     a[tot].c=-c;
 35     return;
 36 }
 37 struct ahh{
 38     int l,r;
 39 }b[503];
 40 int ls[1003];
 41 int s,t;
 42 queue<int>q;
 43 bool sf[1003];
 44 int dis[1003];
 45 inline bool spfa()
 46 {
 47     memset(sf,0,sizeof(sf));
 48     memset(dis,127,sizeof(dis));
 49     sf[s]=1;dis[s]=0;q.push(s);
 50     while(!q.empty())
 51     {
 52         int x=q.front();q.pop();
 53         for(int i=h[x];i;i=a[i].f)
 54         if(dis[a[i].e]>dis[x]+a[i].c&&a[i].v)
 55         {
 56             dis[a[i].e]=dis[x]+a[i].c;
 57             if(!sf[a[i].e])
 58             {
 59                 sf[a[i].e]=1;
 60                 q.push(a[i].e);
 61             }
 62         }
 63         sf[x]=0;
 64     }
 65     return dis[t]<INF;
 66 }
 67 long long ans=0;
 68 int dfs(int x,int al)
 69 {
 70     sf[x]=1;
 71     if(x==t||!al)return al;
 72     int fl=0;
 73     for(int i=h[x];i;i=a[i].f)
 74     if(dis[a[i].e]==dis[x]+a[i].c&&a[i].v&&!sf[a[i].e])
 75     {
 76         int f=dfs(a[i].e,min(al,a[i].v));
 77         if(f)
 78         {
 79             fl+=f;
 80             al-=f;
 81             ans+=f*a[i].c;
 82             a[i].v-=f;
 83             a[i^1].v+=f;
 84             if(!al)break;
 85         }
 86     }
 87     if(!fl)dis[x]=-INF;
 88     return fl;
 89 }
 90 int main()
 91 {
 92     //freopen("a.in","r",stdin);
 93     int n,k;
 94     scanf("%d%d",&n,&k);
 95     int tol=0;
 96     for(int i=1;i<=n;++i)
 97     {
 98         scanf("%d%d",&b[i].l,&b[i].r);
 99         ls[++tol]=b[i].l;
100         ls[++tol]=b[i].r;
101     }
102     //离散
103     sort(ls+1,ls+tol+1);
104     int len=(unique(ls+1,ls+tol+1)-ls)-1;//用unique去重
105     for(int i=1;i<=n;++i)
106     {
107         int ll=lower_bound(ls+1,ls+len+1,b[i].l)-ls;
108         int rr=lower_bound(ls+1,ls+len+1,b[i].r)-ls;
109         con(ll,rr,1,-(b[i].r-b[i].l));//建边
110     }
111     //
112     s=0,t=len+1;
113     for(int i=1;i<len;++i)
114     con(i,i+1,INF,0);
115     con(s,1,k,0);
116     con(len,t,INF,0);
117     //
118     while(spfa())
119     {
120         sf[t]=1;
121         while(sf[t])
122         {
123             memset(sf,0,sizeof(sf));
124             dfs(s,INF);
125         }
126     }
127     cout<<-ans;//输出再取个负就好了
128     return 0;
129 }

原文地址:https://www.cnblogs.com/qwerta/p/9769384.html

时间: 2024-10-08 11:33:32

「网络流24题」「LuoguP3358」 最长k可重区间集问题的相关文章

【网络流24题】No.21 (最长 k 可重区间集问题 最长不相交路径 最大费用流)

[] 输入文件示例input.txt4 21 76 87 109 13 输出文件示例output.txt15 [分析] 直接co题解好了,写得挺全.. [建模方法] 方法1 按左端点排序所有区间,把每个区间拆分看做两个顶点<i.a><i.b>,建立附加源S汇T,以及附加顶点S'. 1.连接S到S'一条容量为K,费用为0的有向边.2.从S'到每个<i.a>连接一条容量为1,费用为0的有向边.3.从每个<i.b>到T连接一条容量为1,费用为0的有向边.4.从每个

网络流 P3358 最长k可重区间集问题

P3358 最长k可重区间集问题 题目描述 对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度. 输入输出格式 输入格式: 的第 1 行有 2 个正整数 n和 k,分别表示开区间的个数和开区间的可重迭数.接下来的 n行,每行有 2 个整数,表示开区间的左右端点坐标. 输出格式: 将计算出的最长 k可重区间集的长度输出 输入输出样例 输入样例#1: 复制 4 2 1 7 6 8 7 10 9 13 输出样例#1: 复制 15 说明 对于100%的数据,1\le

「网络流 24 题」最长 k 可重区间集

给定区间集合$I$和正整数$k$, 计算$I$的最长$k$可重区间集的长度. 区间离散化到$[1,2n]$, $S$与$1$连边$(k,0)$, $i$与$i+1$连边$(k,0)$, $2n$与$T$连边$(k,0)$. 对于每个区间$(l,r)$, $l$与$r$连边$(1,l-r)$. 最小费用相反数就为最大长度 #include <iostream> #include <sstream> #include <algorithm> #include <cst

[网络流 24 题]最长k可重区间集(费用流)

Description 给定实直线L 上n 个开区间组成的集合I,和一个正整数k,试设计一个算法,从开区间集合I 中选取出开区间集合S属于I,使得在实直线L 的任何一点x,S 中包含点x 的开区间个数不超过k,且sum(|z|)z属于S,达到最大.这样的集合S称为开区间集合I的最长k可重区间集.sum(|z|) z属于S称为最长k可重区间集的长度.对于给定的开区间集合I和正整数k,计算开区间集合I的最长k可重区间集的长度. Solution 1.离散化 然后从每个点i向i+1连一条流量为INF,

「网络流24题」 题目列表

「网络流24题」 题目列表 序号 题目标题 模型 题解 1 飞行员配对方案问题 二分图最大匹配 <1> 2 太空飞行计划问题 最大权闭合子图 <2> 3 最小路径覆盖问题 二分图最小路径覆盖 <3> 4 魔术球问题 <4> 5 圆桌问题 <5> 6 最长递增子序列问题 <6> 7 试题库问题 <7> 8 机器人路径规划问题 <8> 9 方格取数问题 二分图最大点权独立集 <9> 10 餐巾计划问题

LibreOJ #6001. 「网络流 24 题」太空飞行计划 最大权闭合图

#6001. 「网络流 24 题」太空飞行计划 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 W 教授正在为国家航天中心计划一系列的太空飞行.每次太空飞行可进行一系列商业性实验而获取利润.现已确定了一个可供选择的实验集合 E={E1,E2,?,Em} E = \{ E_1, E_2, \cdots, E_m \}E={E?1??,E?2??,?,E?m??},和进行这些实验

LiberOJ #6013. 「网络流 24 题」负载平衡 最小费用最大流 供应平衡问题

#6013. 「网络流 24 题」负载平衡 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 G 公司有 n nn 个沿铁路运输线环形排列的仓库,每个仓库存储的货物数量不等.如何用最少搬运量可以使 n nn 个仓库的库存数量相同.搬运货物时,只能在相邻的仓库之间搬运. 输入格式 文件的第 1 11 行中有 1 11 个正整数 n nn,表示有 n nn 个仓库.第 2 22 行中有 n nn 个

LiberOJ #6000. 「网络流 24 题」搭配飞行员 最大匹配

#6000. 「网络流 24 题」搭配飞行员 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 飞行大队有若干个来自各地的驾驶员,专门驾驶一种型号的飞机,这种飞机每架有两个驾驶员,需一个正驾驶员和一个副驾驶员.由于种种原因,例如相互配合的问题,有些驾驶员不能在同一架飞机上飞行,问如何搭配驾驶员才能使出航的飞机最多. 因为驾驶工作分工严格,两个正驾驶员或两个副驾驶员都不能同机飞行. 输入格式 第一

LiberOJ #6002. 「网络流 24 题」最小路径覆盖

#6002. 「网络流 24 题」最小路径覆盖 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:Special Judge 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 给定有向图 G=(V,E) G = (V, E)G=(V,E).设 P PP 是 G GG 的一个简单路(顶点不相交)的集合.如果 V VV 中每个顶点恰好在 P PP 的一条路上,则称 P PP 是 G GG 的一个路径覆盖.P PP 中路径可以从 V VV 的任何一个顶点开始,