传送门c++
这是一个很是经典的费用流的模型。spa
首先由于题目中限制咱们每一个点最多只能选取\(k\)次,所以,由于会有\(k\)次的限制,所以咱们不妨用最大流进行限流,即咱们将源点拆成两个点\(S_0\)以及\(S_1\),从\(S_0\)点向\(S_1\)点连一条流量为k,费用为\(0\)的边。表明最多有大小为\(k\)的流通过全部的边。这样咱们就可以保证,最终经过终点的流量被限死在k,而又由于要求的是最大价值,所以咱们须要求的是最大费用最大流,这个咱们只须要将价值变成负数。code
由于最多会有\(n\)对区间,\(2n\)个点,所以咱们考虑将着\(2n\)个点离散化。离散化后,咱们将这离散化后的\(2n\)个点中离散化后相邻的点都连一条流量为\(inf\),费用为\(0\)的边,表明相邻的点均可以互相到达。以后咱们再将以前的\(n\)对区间的每个区间\([l,r]\),将点\(l\)和点\(r\)之间连一条费用为\(-len_{lr}\),流量为\(1\)的边,表明若是要选取当前区间,则将会花费\(-len{lr}\)的费用以及区间中的全部点都将占用\(1\)点流量。创建好图以后,咱们跑一边最小费用最大流以后取最小费用的相反数便可。get
// luogu-judger-enable-o2 #include <bits/stdc++.h> #define maxn 1006 #define maxm 10005 using namespace std; int head[maxn],cnt=0; int dis[maxn],vis[maxn],sp,ep,maxflow,cost; int n,k; const int INF=0x3f3f3f3f; struct Node{ int to,next,val,cost; }q[maxm<<1]; int L[maxn],R[maxn]; vector<int>vec; void init(){ memset(head,-1, sizeof(head)); cnt=2; maxflow=cost=0; } void addedge(int from,int to,int val,int cost){ q[cnt].to=to; q[cnt].next=head[from]; q[cnt].val=val; q[cnt].cost=cost; head[from]=cnt++; } void add_edge(int from,int to,int val,int cost){ addedge(from,to,val,cost); addedge(to,from,0,-cost); } bool spfa(){ memset(vis,0,sizeof(vis)); memset(dis,0x3f,sizeof(dis)); dis[sp]=0; vis[sp]=1; queue<int>que; que.push(sp); while(!que.empty()){ int x=que.front(); que.pop(); vis[x]=0; for(int i=head[x];i!=-1;i=q[i].next){ int to=q[i].to; if(dis[to]>dis[x]+q[i].cost&&q[i].val){ dis[to]=dis[x]+q[i].cost; if(!vis[to]){ que.push(to); vis[to]=1; } } } } return dis[ep]!=0x3f3f3f3f; } int dfs(int x,int flow){ if(x==ep){ vis[ep]=1; maxflow+=flow; return flow; }//能够到达t,加流 int used=0;//该条路径可用流量 vis[x]=1; for(int i=head[x];i!=-1;i=q[i].next){ int to=q[i].to; if((vis[to]==0||to==ep)&&q[i].val!=0&&dis[to]==dis[x]+q[i].cost){ int minflow=dfs(to,min(flow-used,q[i].val)); if(minflow!=0){ cost+=q[i].cost*minflow; q[i].val-=minflow; q[i^1].val+=minflow; used+=minflow; } //能够到达t,加费用,扣流量 if(used==flow)break; } } return used; } int mincostmaxflow(){ while(spfa()){ vis[ep]=1; while(vis[ep]){ memset(vis,0,sizeof(vis)); dfs(sp,INF); } } return maxflow; } int main() { scanf("%d%d",&n,&k); init(); for(int i=1;i<=n;i++){ scanf("%d%d",&L[i],&R[i]); if(L[i]>R[i]) swap(L[i],R[i]); vec.push_back(L[i]); vec.push_back(R[i]); } sort(vec.begin(),vec.end()); int sz=vec.size(); sp=sz+1,ep=sz+2; add_edge(sp,1,k,0); add_edge(sz,ep,k,0); for(int i=1;i<sz;i++) add_edge(i,i+1,k,0); for(int i=1;i<=n;i++){ int l=lower_bound(vec.begin(),vec.end(),L[i])-vec.begin(); int r=lower_bound(vec.begin(),vec.end(),R[i])-vec.begin(); add_edge(l+1,r+1,1,vec[l]-vec[r]); } mincostmaxflow(); printf("%d\n",-cost); return 0; }