COGS743. [网络流24题] 最长k可重区间集
743. [网络流24题] 最长k可重区间集
★★★ 输入文件:interv.in
输出文件:interv.out
简单对比
时间限制:1 s 内存限制:128 MB
- «问题描述:
- «编程任务:
- 对于给定的开区间集合I和正整数k,计算开区间集合I的最长k可重区间集的长度。
- «数据输入:
- 由文件interv.in提供输入数据。文件的第1 行有2 个正整数n和k,分别表示开区间的
- 个数和开区间的可重迭数。接下来的n行,每行有2个整数,表示开区间的左右端点坐标。
- «结果输出:
- 程序运行结束时,将计算出的最长k可重区间集的长度输出到文件interv.out中。
- 输入文件示例 输出文件示例
- interv.in
- 4 2
- 1 7
- 6 8
- 7 10
9 13
interv.out
- 15
这样的区间建图比较好想,因为以前做过用最短路的最小区间覆盖问题,想法类似
BYVOID:
离散化所有区间的端点,把每个端点看做一个顶点,建立附加源S汇T。
1、从S到顶点1(最左边顶点)连接一条容量为K,费用为0的有向边。
2、从顶点2N(最右边顶点)到T连接一条容量为K,费用为0的有向边。
3、从顶点i到顶点i+1(i+1<=2N),连接一条容量为无穷大,费用为0的有向边。
4、对于每个区间[a,b],从a对应的顶点i到b对应的顶点j连接一条容量为1,费用为区间长度的有向边。
两点:
1.相邻的连一条边,避免了每个点都和s t连边
2.容量限制为k,经过每个点的边数一定<=k
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long ll; const int N=1005,M=1e5+5,INF=1e9; 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,mp[N],m,l[N],r[N],s,t; int Bin(int v){ int l=1,r=m; while(l<=r){ int mid=(l+r)>>1; if(mp[mid]==v) return mid; if(v<mp[mid]) r=mid-1; else l=mid+1; } return -1; } struct edge{ int v,ne,c,f,w; }e[M<<1]; int cnt,h[N]; inline void ins(int u,int v,int c,int w){ //printf("ins %d %d %d %d %d %d\n",u,v,c,w,mp[u],mp[v]); cnt++; e[cnt].v=v;e[cnt].c=c;e[cnt].f=0;e[cnt].w=w; e[cnt].ne=h[u];h[u]=cnt; cnt++; e[cnt].v=u;e[cnt].c=0;e[cnt].f=0;e[cnt].w=-w; e[cnt].ne=h[v];h[v]=cnt; } void build(){ s=0;t=m+1; ins(s,1,k,0);ins(m,t,k,0); for(int i=1;i<m;i++) ins(i,i+1,INF,0); for(int i=1;i<=n;i++) ins(Bin(l[i]),Bin(r[i]),1,-(r[i]-l[i])); } int q[N],head,tail,d[N],inq[N],pre[N],pos[N]; inline void lop(int &x){if(x==N) x=1;else if(x==0) x=N-1;} bool spfa(){ memset(d,127,sizeof(d)); memset(inq,0,sizeof(inq)); head=tail=1; q[tail++]=s;inq[s]=1;d[s]=0; pre[t]=-1; while(head!=tail){ int u=q[head++];inq[u]=0;lop(head); for(int i=h[u];i;i=e[i].ne){ int v=e[i].v,w=e[i].w; if(e[i].c>e[i].f&&d[v]>d[u]+w){ d[v]=d[u]+w; pos[v]=i;pre[v]=u; if(!inq[v]){ inq[v]=1; if(d[v]<d[q[head]]) head--,lop(head),q[head]=v; else q[tail++]=v,lop(tail); } } } } return pre[t]!=-1; } int mcmf(){ int flow=0,cost=0; while(spfa()){ int f=INF; for(int i=t;i!=s;i=pre[i]) f=min(f,e[pos[i]].c-e[pos[i]].f); flow+=f;cost+=-d[t]*f;//printf("flow %d\n",flow); for(int i=t;i!=s;i=pre[i]){ int p=pos[i]; e[p].f+=f; e[((p-1)^1)+1].f-=f; } } return cost; } int main(){ freopen("interv.in","r",stdin); freopen("interv.out","w",stdout); n=read();k=read(); for(int i=1;i<=n;i++) mp[++m]=l[i]=read(),mp[++m]=r[i]=read(); sort(mp+1,mp+1+m); int p=0;mp[++p]=mp[1]; for(int i=2;i<=m;i++) if(mp[i]!=mp[i-1]) mp[++p]=mp[i]; m=p; build(); printf("%d\n",mcmf()); }
Copyright:http://www.cnblogs.com/candy99/