题目描述
对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度。
输入输出格式
输入格式:的第 1 行有 2 个正整数 n和 k,分别表示开区间的个数和开区间的可重迭数。接下来的 n行,每行有 2 个整数,表示开区间的左右端点坐标。
输出格式:将计算出的最长 k可重区间集的长度输出
输入输出样例
说明
对于100%的数据,1≤n≤500 ,1≤k≤3。
这个题貌似之前不停地打开然后放弃掉。。貌似主要原因是看不懂题面让我干些什么。。。上午的考试让我有了充足的时间观察题面,发现道理就是给了一堆区间,然后每个点不能被超过k个区间覆盖,每个区间的价值是它的长度,求最大价值。
然后一开始的时候一直都是想着怎么把互相覆盖这个条件把握好,然后各种如果他们有交集就连边之类的。。。后来发现并不可行,总是无法维护好。
然后看了题解豁然开朗,貌似自己的拆点连边什么的都没什么问题,甚至伪超级源这种东西都想到了,然而思路还是局限了我,这个题要向与自己没有交集的区间连边。然后去跑最大费用即可。。。真是可惜了。。。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<map> #define ll long long #define inf 50000000 #define re register #define min(a,b) a<b?a:b using namespace std; struct po{ int nxt,to,w,dis; }; po edge[250001]; struct len{ int l,r; }; len a[1002]; int head[1050],num=-1,n,m,s,t,k,S; int dis[1050],b[1050],tot; inline int read() { int x=0,c=1; char ch=‘ ‘; while((ch>‘9‘||ch<‘0‘)&&ch!=‘-‘)ch=getchar(); while(ch==‘-‘)c*=-1,ch=getchar(); while(ch<=‘9‘&&ch>=‘0‘)x=x*10+ch-‘0‘,ch=getchar(); return x*c; } inline void add_edge(int from,int to,int w,int dis) { edge[++num].nxt=head[from]; edge[num].to=to; edge[num].w=w; edge[num].dis=dis; head[from]=num; } inline void add(int from,int to,int w,int dis) { add_edge(from,to,w,dis); add_edge(to,from,0,-dis); } inline bool spfa() { memset(dis,50,sizeof(dis)); memset(b,0,sizeof(b)); deque<int> q; dis[t]=0; b[t]=1; q.push_back(t); while(!q.empty()){ int u=q.front(); q.pop_front(); b[u]=0; for(re int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(edge[i^1].w>0&&dis[v]>dis[u]-edge[i].dis){ dis[v]=dis[u]-edge[i].dis; if(!b[v]){ b[v]=1; if(!q.empty()&&dis[v]<dis[q.front()]) q.push_front(v); else q.push_back(v); } } } } return dis[s]<inf; } inline int dfs(int u,int low) { b[u]=1; if(u==t) return low; int diss=0; for(re int i=head[u];i!=-1;i=edge[i].nxt){ int v=edge[i].to; if(edge[i].w&&!b[v]&&dis[v]==dis[u]-edge[i].dis){ int check=dfs(v,min(low,edge[i].w)); if(check){ tot+=edge[i].dis*check; low-=check; diss+=check; edge[i].w-=check; edge[i^1].w+=check; if(low==0) break; } } } return diss; } inline int max_flow(){ int ans=0; while(spfa()){ b[t]=1; while(b[t]){ memset(b,0,sizeof(b)); ans+=dfs(s,inf); } } } inline bool cmp(len x,len y) { if(x.l<y.l) return 1; else if(x.l==y.l&&x.r<y.r) return 1; return 0; } int main() { memset(head,-1,sizeof(head)); n=read();k=read(); s=0;t=n+n+2; S=n+n+1; add(s,S,k,0); for(re int i=1;i<=n;i++){ a[i].l=read();a[i].r=read(); if(a[i].l>a[i].r) swap(a[i].l,a[i].r); } sort(a+1,a+n+1,cmp); for(re int i=1;i<n;i++) for(re int j=i+1;j<=n;j++) if(a[i].r<=a[j].l) add(i+n,j,1,0); for(re int i=1;i<=n;i++){ add(S,i,1,0);add(i+n,t,1,0);add(i,i+n,1,-a[i].r+a[i].l); } max_flow(); cout<<-tot; }