[网络流24题] 最长k可重区间集
对于区间 u->v ,连接边 u->v,权值为-len,容量为1,之后对每个点 i->i+1,连边 i->i+1,容量为k,权值为0,求区间最左端点到最右端点的费用流,费用相反数即为答案。
// q.c
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
const int M=500+5,INF=(int)1e8;
struct Edge {
int u,v,nex,cost,flow,cap; Edge() {}
Edge(int a,int b,int c,int d,int e,int f):u(a),v(b),nex(c),cost(d),flow(e),cap(f) {}
}ed[M<<3];
int cnt,head[M<<1];
void add_edge(int a,int b,int c,int d) {
ed[cnt]=Edge(a,b,head[a], c,0,d); head[a]=cnt++;
ed[cnt]=Edge(b,a,head[b],-c,0,0); head[b]=cnt++;
}
struct Dinic {
int n,s,t,dis[M<<1],pre[M<<1],lim[M<<1]; bool in[M<<1]; queue<int> Q;
Dinic():n(0),s(0),t(0) {
mem(dis); mem(pre); mem(lim); mem(in);
while(!Q.empty()) Q.pop();
}
bool spfa(int &Flow,int &Cost) {
for(int i=0;i<=n;i++) dis[i]=lim[i]=INF,pre[i]=in[i]=0;
dis[s]=0; in[s]=true; Q.push(s);
int u,i; Edge e;
while(!Q.empty()) {
u=Q.front(); Q.pop(); in[u]=false;
for(i=head[u];i!=-1;i=ed[i].nex) {
e=ed[i];
if(dis[u]+e.cost<dis[e.v]&&e.cap>e.flow) {
dis[e.v]=dis[u]+e.cost; pre[e.v]=i;
lim[e.v]=min(lim[u],e.cap-e.flow);
if(!in[e.v]) in[e.v]=true,Q.push(e.v);
}
}
}
if(dis[t]==INF) return false;
Flow+=lim[t];
Cost+=lim[t]*dis[t];
u=t;
while(u!=s) {
i=pre[u]; ed[i].flow+=lim[t];
ed[i^1].flow-=lim[t]; u=ed[i].u;
}
return true;
}
int solve(int x,int y,int z) {
s=x; t=y; n=z;
int Flow=0,Cost=0;
for(;spfa(Flow,Cost););
return Cost;
}
}DC;
struct Data {
int x,y,z;
bool operator < (const Data &A) const {
if(x!=A.x) return x<A.x;
return y<A.y;
}
}da[M],tmp[M<<1];
int ref[M<<1];
int main() {
freopen("interv.in","r",stdin);
freopen("interv.out","w",stdout);
memset(head,-1,sizeof(head));
int n,k,m=0,a,b,p,q,tot=0;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++) {
scanf("%d%d",&a,&b);
if(a>=b) continue;
++m;
q=m<<1; p=q-1;
da[m].x=p,da[m].y=q;
da[m].z=b-a;
tmp[p].x=a,tmp[p].y=p;
tmp[q].x=b,tmp[q].y=q;
}
sort(tmp+1,tmp+(m<<1)+1);
for(int i=1;i<=(m<<1);i++) {
if(tmp[i].x!=tmp[i-1].x) ref[tmp[i].y]=++tot;
else ref[tmp[i].y]=tot;
}
for(int i=1;i<=m;i++) {
da[i].x=ref[da[i].x];
da[i].y=ref[da[i].y];
add_edge(da[i].x,da[i].y,-(da[i].z),1);
}
for(int i=1;i<tot;i++) {
add_edge(i,i+1,0,INF);
}
add_edge(0,1,0,k);
add_edge(tot,tot+1,0,k);
printf("%d\n",-DC.solve(0,tot+1,tot+1));
return 0;
}

浙公网安备 33010602011771号