您的位置:首页 > 其它

洛谷P3358:最长k可重区间集问题(最大费用最大流)

2018-03-04 10:08 375 查看
题目



      对于给定的开区间集合 I 和正整数 k,计算开区间集合 I 的最长 k可重区间集的长度。

题解
      我先给大家解释一下开区间,意思就是有区间集合(a,b),这个集合除去点a,b所构成的集合称为开区间(a,b)。
      这道题看上去很复杂,其实就是可以转化为找k个集合,每个集合内的区间互不相交。
      我这么一说,悟性高的同志都跑去打mcmf板子了。
      先按照左端点为第一关键字,右端点为第二关键字,排一次序,每个区间拆成两个点,用来控制流量和制造费用。a区间拆成a点和a'点。
      1.对于每个区间,i到i'连一条流量为1费用为长度的边,表示选择这条边会获得长度的价值。
      2.对于每两个区间i,j(1<=i<j<=n),i'到j连一条流量为1费用为0的边,表示选择i区间时可以选择j区间。
      3.xbegin到i连一条流量为1费用为0的边,i'到end连一条流量为1费用为0的边。
      4.最后别忘了”只能选择k个集合“这个条件,超超超级源begin到xbegin连一条流量为k费用为0的边。
贴代码#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<queue>
#define INF 1e9
using namespace std;

int n,k;
int begin,end;
struct node{int x,y;};
node p[1010];
int first[1010];
struct edge{int x,y,c,cos,next;};
edge s[100010];
int len=1;
queue<int> f;
int h[1010];
bool tf[1010];
int mmin[1010];
int ip[1010];

void ins(int x,int y,int c,int cos)
{
len++;
s[len].x=x;s[len].y=y;s[len].c=c;s[len].cos=cos;s[len].next=first[x];first[x]=len;
len++;
s[len].x=y;s[len].y=x;s[len].c=0;s[len].cos=-cos;s[len].next=first[y];first[y]=len;
}

bool check(int x,int y)
{
if(p[x].y<=p[y].x) return true;
return false;
}

bool SPFA(int&cost,int&flow)
{
f.push(begin);
memset(h,63,sizeof(h));
h[begin]=0;
mmin[begin]=INF;
tf[begin]=true;
while(!f.empty())
{
int x=f.front();
f.pop();
tf[x]=false;
for(int i=first[x];i!=0;i=s[i].next)
{
int y=s[i].y;
if(h[y]>h[x]+s[i].cos && s[i].c>0)
{
h[y]=h[x]+s[i].cos;
ip[y]=i;
mmin[y]=min(mmin[x],s[i].c);
if(tf[y]==false)
{
tf[y]=true;
f.push(y);
}
}
}
}
if(h[end]==1061109567) return false;
flow+=mmin[end];
cost+=mmin[end]*h[end];
int now=end;
while(now!=begin)
{
int i=ip[now];
s[i].c-=mmin[end];
s[i^1].c+=mmin[end];
now=s[i].x;
}
return true;
}

int cost_flow()
{
int cost=0,flow=0;
while(SPFA(cost,flow));
return -cost;
}

void qsort(int x,int y)
{
int i=x,j=y;
node m,t;
m=p[(x+y)/2];
while(i<=j)
{
while(p[i].x<m.x) i++;
while(p[j].x>m.x) j--;
if(i<=j)
{
t=p[i];p[i]=p[j];p[j]=t;
i++;j--;
}
}
if(x<j) qsort(x,j);
if(i<y) qsort(i,y);
}

int main()
{
scanf("%d %d",&n,&k);
begin=n*2+1,end=n*2+2;
ins(begin,0,k,0);
for(int i=1;i<=n;i++)
scanf("%d %d",&p[i].x,&p[i].y);
qsort(1,n);
for(int i=1;i<=n;i++)
{
int x=p[i].x,y=p[i].y;
ins(0,i,INF,0);
ins(n+i,end,INF,0);
ins(i,n+i,1,-(y-x));
for(int j=i+1;j<=n;j++)
if(check(i,j))
ins(n+i,j,1,0);
}
printf("%d",cost_flow());
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐