题目描述
对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度。
输入输出格式
输入格式:的第 1 行有 2 个正整数 n和 k,分别表示开区间的个数和开区间的可重迭数。接下来的 n行,每行有 2 个整数,表示开区间的左右端点坐标。
输出格式:将计算出的最长 k可重区间集的长度输出
输入输出样例
说明
对于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 }