您的位置:首页 > 其它

bzoj2034[2009国家集训队]最大收益

2015-12-13 11:58 399 查看
我们看完题目,大概都会有点想法,我们可以不断地贪心插入这个任务

实际上就是,我们把这些任务和对面的时间点看成一个二分图,于是我们可以思考二分图匹配,并用二分来查找时间点,类似匈牙利的思想把任务往后挤,挤不动就不插入

最开始的时候并没有看FQW的论文,然后稀里糊涂的写了一段又臭又长的代码,WA了。

FQW的实现还是比较简单的,而且那篇论文里面几乎把各种优化统统列出来了。

总体复杂度(N2),记得ans要是long long的,不然就会像我一样找了好久找不到措

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<algorithm>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
inline LL read()
{
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
#define N 5005
#define inf 1000000007
struct dian
{
int be,en,v;
}d
;
int f
,b
;
//bool v
;
int n;
LL ans=0;

bool timecom(dian a,dian b)
{
if (a.be==b.be) return a.en<b.en;
else return a.be<b.be;
}

bool vcom(dian a,dian b)
{
return a.v>b.v;
}

void lishan()
{
sort(d+1,d+n+1,timecom);
int t=0;
fo(i,1,n)
{
t=max(t+1,d[i].be);
b[i]=t;
}
b[n+1]=inf;
}

int erfen(int k,int l,int r)
{
// cout<<d[k].be<<' '<<d[k].en<<' '<<l<<' '<<r<<' '<<b[l]<<' '<<b[r]<<' '<<endl;
int mid=(l+r)>>1;
if(d[k].be<=b[mid]&&b[mid]<=d[k].en)
{
while(d[k].be<=b[mid]) mid--;
return mid+1;
}
if(d[k].be<=b[mid]) return erfen(k,l,mid-1);
if(b[mid]<=d[k].en) return erfen(k,mid+1,r);
}

bool match(int k,int x)
{
if(d[k].en<b[x])return 0;
if(f[x]==0)
{
f[x]=k;
return 1;
}
if(d[k].en>d[f[x]].en) return match(k,x+1);
else
{
if(match(f[x],x+1))
{
f[x]=k;
return 1;
}
}
return 0;
}

void work()
{
sort(d+1,d+n+1,vcom);
fo(i,1,n)
{
int j=erfen(i,1,n);
// cout<<i<<' '<<j<<' '<<n<<endl;
if(match(i,j))ans+=d[i].v;
// cout<<ans<<' '<<d[i].v<<endl;
}
}

int main()
{
n=read();
fo(i,1,n)
{
d[i].be=read();
d[i].en=read();
d[i].v=read();
}
lishan();
work();
cout<<ans<<endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  二分图匹配