«
问题描述:
给定实直线 L 上 n 个开区间组成的集合 I ,和一个正整数 k ,试设计一个算法,从开区间集合 I 中选取出开区间集合 S Í I ,使得在实直线 L 的任何一点 x , S 中包含点 x 的开区间
个数不超过 k ,且sigma(|z|) 达到最大。这样的集合 S 称为开区间集合 I 的最长 k 可重区间集。
对于给定的开区间集合 I 和正整数 k ,计算开区间集合 I 的最长 k 可重区间集的长度。
« 数据输入:
由文件 input.txt 提供输入数据。文件的第 1 行有 2 个正整数 n 和 k ,分别表示开区间的个数和开区间的可重迭数。接下来的 n 行,每行有 2 个整数,表示开区间的左右端点坐标。
« 结果输出 :
给定实直线 L 上 n 个开区间组成的集合 I ,和一个正整数 k ,试设计一个算法,从开区间集合 I 中选取出开区间集合 S Í I ,使得在实直线 L 的任何一点 x , S 中包含点 x 的开区间
个数不超过 k ,且sigma(|z|) 达到最大。这样的集合 S 称为开区间集合 I 的最长 k 可重区间集。
sigma(|z|)称为最长k 可重区间集的长度。
对于给定的开区间集合 I 和正整数 k ,计算开区间集合 I 的最长 k 可重区间集的长度。
« 数据输入:
由文件 input.txt 提供输入数据。文件的第 1 行有 2 个正整数 n 和 k ,分别表示开区间的个数和开区间的可重迭数。接下来的 n 行,每行有 2 个整数,表示开区间的左右端点坐标。
« 结果输出 :
程序运行结束时,将计算出的最长 k 可重区间集的长度输出到文件 output.txt中。
输入文件示例
input.txt
4 2
1 7
6 8
7 10
9 13
输出文件示例
output.txt
15
题解:这道题属于网路流中的最大权不相交路径问题
input.txt
4 2
1 7
6 8
7 10
9 13
输出文件示例
output.txt
15
题解:这道题属于网路流中的最大权不相交路径问题
先离散化,把原来的n的线段的端点离散化成1~2n这些数(这步是为了后面的处理更加方便)
建图方式:
1、超级源s到1号点(也就是最左边线段的左端点)连一条流量为k 费用为0的有向边
2、2n号点到超级汇t(也就是最右边线段的右端点)连一条流量为k 费用为0的有向边
3、除s、t外的所有点x到x+1连一条流量为无限大 费用为0的有向边
4、原来的所有线段的左端点到右端点连一条流量为1 费用为线段长度(在这题中=右端点-左端点,但因为是开区间,所以两头都不能要啊,应该=右端点-左端点-1)的有向边
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <memory.h>
#include <math.h>
#include <queue>
#include <stack>
#include <map>
#include <vector>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <float.h>
using namespace std;
const int oo=1000000005;
const int Maxn=100005;
const int Maxm=100005;
int i,ans,n,k,s,t,len,x;
int head[Maxn];
int lz[Maxn];
int l[Maxn];
int dis[Maxn];
int a[Maxn];
int vis[Maxn];
int pre[Maxn];
int rz[Maxn];
int r[Maxn];
struct node{
int num,z;//num是数值 z是在原数组中的位置 l数组为i r数组为n+i
node(){
num=z=0;
}
node(int x,int y){
num=x;z=y;
}
bool operator < (const node &s) const{
return num<s.num;
}
} lsh[Maxn<<1];
struct edge{
int u,v,c,f,w,next;
edge(){
u=v=c=f=w=0;
next=-1;
}
edge(int x,int y,int z,int a,int s,int d){
u=x;v=y;c=z;f=a;w=s;next=d;
}
} e[Maxm];
void add(int u,int v,int c,int f,int w){
len++;
e[len]=edge(u,v,c,f,w,head[u]);
head[u]=len;
}
int spfa(int s,int t,int m){
int x;
int sum=0;
queue <int> q;
for(i=1;i<=m;i++){
vis[i]=0;
dis[i]=oo;
a[i]=oo;
}
q.push(s);
vis[s]=1;
dis[s]=0;
a[s]=oo;
while(!q.empty()){
x=q.front();
for(i=head[x];i!=-1;i=e[i].next)
if(dis[x]+e[i].w<dis[e[i].v]&&e[i].c>e[i].f){
dis[e[i].v]=dis[x]+e[i].w;
pre[e[i].v]=i;
a[e[i].v]=min(e[i].c-e[i].f,a[x]);
if(!vis[e[i].v]){
q.push(e[i].v);
vis[e[i].v]=1;
}
}
q.pop();
vis[x]=0;
}
if(dis[t]==oo)
return -1;
x=t;
while(x!=s){
e[pre[x]].f+=a[t];
e[pre[x]^1].f-=a[t];
sum+=a[t]*e[pre[x]].w;
x=e[pre[x]].u;
//printf("sum=%d\n",sum);
}
return sum;
}
int main(){
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
scanf("%d %d",&n,&k);
for(i=1;i<=2*n+2;i++)
head[i]=-1;
len=-1;
for(i=1;i<=n;i++){
scanf("%d %d",&l[i],&r[i]);
lsh[2*i-1]=node(l[i],i);
lsh[2*i]=node(r[i],n+i);
}
sort(lsh+1,lsh+1+(n<<1));
for(i=1;i<=(n<<1);i++){
if(lsh[i].z<=n)
lz[lsh[i].z]=i;
else
rz[lsh[i].z-n]=i;
}
s=(n<<1)+1;
t=(n<<1)+2;
add(s,1,k,0,0);
add(1,s,0,0,0);
add(n*2,t,k,0,0);
add(t,n*2,0,0,0);
for(i=1;i<(n<<1);i++){
add(i,i+1,oo,0,0);
add(i+1,i,0,0,0);
}
for(i=1;i<=n;i++){
add(lz[i],rz[i],1,0,-(r[i]-l[i]));
add(rz[i],lz[i],0,0,r[i]-l[i]);
}
//for(i=0;i<=len;i++)
// printf("%d:%d %d %d %d %d\n",i,e[i].u,e[i].v,e[i].c,e[i].f,e[i].w);
while(1){
x=spfa(s,t,n*2+2);
if(x==-1)
break;
ans+=x;
//printf("%d\n",-ans);
}
printf("%d\n",-ans);
return 0;
}