确实比较难想
正解有两种
借鉴一下学长的图
首先离散化
第一种
这样首先保证每个点都不会覆盖超过$k$次
那么对于一个区间后面的区间,它对这个区间内的点是没有影响的,故建一条如图所示的边
第二种
当选择了一个区间$(l,r)$后,相当于$(l,r)$这个区间内的点少了一次可以被选择的机会
所以从$l$向$r$连边
代码为第2种
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> #include<vector> #define AddEdge(x,y,z,f) add_edge(x,y,z,f),add_edge(y,x,-z,0) using namespace std; const int MAXN=1e5+10; const int INF=1e6+10; inline int read() { char c=getchar();int x=0,f=1; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } int N,K,S,T; int anscost=0; struct node { int u,v,w,f,nxt; }edge[MAXN]; int head[MAXN],num=2; inline void add_edge(int x,int y,int z,int f) { edge[num].u=x; edge[num].v=y; edge[num].w=z; edge[num].f=f; edge[num].nxt=head[x]; head[x]=num++; } int Pre[MAXN],vis[MAXN],dis[MAXN]; bool SPFA() { queue<int>q; memset(dis,0xf,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[S]=0; q.push(S); while(q.size()!=0) { int p=q.front();q.pop(); vis[p]=0; for(int i=head[p];i!=-1;i=edge[i].nxt) { if(dis[edge[i].v]>dis[p]+edge[i].w&&edge[i].f) { dis[edge[i].v]=dis[p]+edge[i].w; Pre[edge[i].v]=i; if(!vis[edge[i].v]) vis[edge[i].v]=1,q.push(edge[i].v); } } } return dis[T]<=INF; } void f() { int nowflow=INF; for(int now=T;now!=S;now=edge[Pre[now]].u) nowflow=min(nowflow,edge[Pre[now]].f); for(int now=T;now!=S;now=edge[Pre[now]].u) edge[Pre[now]].f-=nowflow, edge[Pre[now]^1].f+=nowflow; anscost+=nowflow*dis[T]; } void MCMF() { int ans=0; while(SPFA()) f(); printf("%d ",-anscost); } int L[MAXN],R[MAXN],date[MAXN],tot=0; int main() { #ifdef WIN32 freopen("a.in","r",stdin); #else #endif memset(head,-1,sizeof(head)); N=read(),K=read(); S=0,T=2*N+1; for(int i=1;i<=N;i++) { L[i]=read();R[i]=read(); date[++tot]=L[i], date[++tot]=R[i]; } sort(date+1,date+N*2+1); int num=unique(date+1,date+2*N+1)-date-1; for(int i=1;i<=N;i++) L[i]=lower_bound(date+1,date+num-1,L[i])-date, R[i]=lower_bound(date+1,date+num+1,R[i])-date; for(int i=1;i<=num-1;i++) AddEdge(i,i+1,0,INF); for(int i=1;i<=N;i++) AddEdge(L[i],R[i],-(date[R[i]]-date[L[i]]),1); AddEdge(S,1,0,K); AddEdge(num,T,0,INF); MCMF(); return 0; }