原题:
https://jzoj.net/senior/#contest/show/2043/0
题目描述:
GDOI商场推出优惠活动,以超低价出售若干种商品。但是,商场为避免过分亏本,规定某些商品不能同时购买,而且每种超低价商品只能买一件。身为顾客的你想获得最大的实惠,也就是争取节省最多的钱。经过仔细研究,发现商场出售的超低价商品中,不存在以下情况:
n(n>=3)种商品C1,C2,…..,Cn,其中Ci,Ci+1是不能同时购买的(i=1,2…,n-1)并且C1, Cn也不能同时购买。
编程计算可以节省的最大金额数。
输入:
第一行两个整数K,M(1<=K<=1000).其中K表示超低价商品数。K种商品的编号依次为1,2,…,K。M表示不能同时购买的商品对数.接下来K行,第i行有一个整数Xi表示购买编号为i的商品可以节省的金额(1<=Xi<=100).再接下来M行,每行两个数A ,B,表示A和B不能同时购买,1<=A<=K,1<=B<=K,A<>B
输出:
仅一个整数,表示能节省的最大金额数。
样例输入:
3 1 1 1 1 1 2
样例输出:
2
分析:
经典的树形DP······
实现:
uses math;
var
p,t:array[1..1000,0..500]of longint;
c:array[1..1000]of longint;
v:array[1..1000]of boolean;
f:array[1..2,1..1000]of longint;
n,m,a,b,s,i:longint;
procedure make(x:longint);
var
i:longint;
begin
v[x]:=true;
for i:=1 to p[x,0] do
if not v[p[x,i]] then
begin
t[x,0]:=t[x,0]+1;
t[x,t[x,0]]:=p[x,i];
make(p[x,i]);
end;
end;
procedure dg(x:longint);
var
i:longint;
begin
if t[x,0]=0 then
begin
f[1,x]:=0;
f[2,x]:=c[x];
exit;
end;
for i:=1 to t[x,0] do dg(t[x,i]);
for i:=1 to t[x,0] do
begin
f[1,x]:=f[1,x]+max(f[1,t[x,i]],f[2,t[x,i]]);
f[2,x]:=f[2,x]+f[1,t[x,i]];
end;
f[2,x]:=f[2,x]+c[x];
end;
begin
readln(n,m);
for i:=1 to n do readln(c[i]);
for i:=1 to m do
begin
readln(a,b);
p[a,0]:=p[a,0]+1;p[a,p[a,0]]:=b;
p[b,0]:=p[b,0]+1;p[b,p[b,0]]:=a;
end;
for i:=1 to n do
if p[i,0]=0 then s:=s+c[i]
else
if not v[i] then
begin
make(i);
dg(i);
s:=s+max(f[1,i],f[2,i]);
end;
writeln(s);
end.