您的位置:首页 > 其它

GDKOI2015D2T1

2016-01-27 13:46 225 查看
题目大意:有一个二分图,对于左边的第i个点,权值为a[i],右边的第i个点权值b[i]。现图中有m条边,第i条边连接s[i],t[i]两点,权值为a[s[i]]+b[s[i]],选择其中若干条边,使总权值最大,但是选出来的边两两不相交。

这道题近似于codevs上的线段覆盖,于是在实现上我们也用上一个近似于线段覆盖的方法来完成这道题(好扯淡……):

1.      读入全部数据

2.      将所有的边以起点为第一关键字(升序),终点为第二关键字(降序)进行排序

3.      DP,f[i]表示在右边前i个点(包括i)的最大权值,那么我们有

f[t[i]]= max(f[t[i]],a[s[i]]+b[t[i]])   (t[i]=1)

      max(f[t[i]],max{f[t[i]-1]}+a[s[i]]+b[t[i]]) (t[i]>1)

那么,麻烦就麻烦在不能直接把前t[i]-1个点里面的最大f值用打擂台的方式找出来,那么怎么办呢?用线段树进行优化。在第3步里面,先把后面的公式的值用k存起来,如果k>f[t[i]],那么f[t[i]]=k再把f[t[i]]存入线段树中。这样一来,我们在求t[i]>1的k值的时候就可以大大加快速度

OK,上代码:

type tpoint=^tppoint;
tppoint=record
l,r,mid:longint;
max:longint;
lc,rc:tpoint;
end;
edge=record s,t:longint;end;
var e:array[1..500000]of edge;
p,q,f:array[1..100000]of longint;
head:tpoint;
n,m,i,j,k:longint;
procedure sort(l,r: longint);
var i,j:longint;x,y:edge;
begin
i:=l;
j:=r;
x:=e[(l+r) div 2];
repeat
while (e[i].s<x.s)or(e[i].s=x.s)and(e[i].t>x.t) do
inc(i);
while (x.s<e[j].s)or(x.s=e[j].s)and(x.t>e[j].t) do
dec(j);
if not(i>j) then
begin
y:=e[i];
e[i]:=e[j];
e[j]:=y;
inc(i);
j:=j-1;
end;
until i>j;
if l<j then
sort(l,j);
if i<r then
sort(i,r);
end;
function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end;
procedure build(var p:tpoint;l,r:longint);
begin
new(p);
p^.l:=l;
p^.r:=r;
p^.mid:=(l+r)div 2;
if l=r then
begin
p^.max:=0;
p^.lc:=nil;
p^.rc:=nil;
exit;
end;
build(p^.lc,l,p^.mid);
build(p^.rc,p^.mid+1,r);
p^.max:=0;
end;
procedure update(var p:tpoint;x,value:longint);
begin
if p^.l=p^.r then
begin
p^.max:=value;
exit;
end;
if x<=p^.mid then update(p^.lc,x,value)
else update(p^.rc,x,value);
p^.max:=max(p^.lc^.max,p^.rc^.max);
end;
function query(p:tpoint;l,r:longint):Longint;
var ans:longint;
begin
if l>r then exit(0);
if p=nil then exit(0);
if p^.r<=r then
exit(p^.max);
ans:=query(p^.lc,l,r);
if p^.mid+1<=r then ans:=max(ans,query(p^.rc,l,r));
exit(ans);
end;
begin
read(n,m);
if m=0 then
begin
writeln(0);
exit;
end;
build(head,1,n);
for i:=1 to m do
read(e[i].s,e[i].t);
for i:=1 to n do
read(q[i]);
for i:=1 to n do
read(p[i]);
sort(1,m);
for i:=1 to m do
begin
if e[i].t<>1 then k:=query(head,1,e[i].t-1)+p[e[i].s]+q[e[i].t]
else k:=p[e[i].s]+q[1];
if k>f[e[i].t] then
begin
update(head,e[i].t,k);
f[e[i].t]:=k;
end;
end;
writeln(query(head,1,n));
end.
代码片:https://code.csdn.net/snippets/1567138
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: