Description
Joe觉得云朵很美,决定去山上的商店买一些云朵。商店里有n朵云,云朵被编号为1,2,……,n,并且每朵云都有一个价值。但是商店老板跟他说,一些云朵要搭配来买才好,所以买一朵云则与这朵云有搭配的云都要买。
但是Joe的钱有限,所以他希望买的价值越多越好。
Input
第1行n,m,w,表示n朵云,m个搭配,Joe有w的钱。
第2到n+1行,每行ci,di表示i朵云的价钱和价值。
第n+2到n+1+m行,每行表示ui,vi,表示买ui就必须买vi,同理,如果买vi就必须买ui。
Output
一行,表示可以获得的最大价值。
Sample Input
5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2
Sample Output
1
Hint
30%的数据保证:n<=100
50%的数据保证:n<=1,000;m<=100;w<=1,000
100%的数据保证:n<=10,000;0<=m<=5000;w<=10,000
这道题目是dp+并查集优化。首先题目说买一朵云则与这朵云有搭配的云都要买,那么我们可以把全部有搭配的云都合并起来,变成一件物品。用01背包求出答案。
F[I,j]=max(f[i-1,j],f[i-1,j-a[i]]+b[i]) (1<=i<=n,1<=j<=w)
(A为代价,B为价值)
标程:
var
a:array [1..10000,1..2] of longint;
p,b,f,c:array [0..10000] of longint;
n,m,i,j,w,x,y,k:longint;
function find(x:longint):longint;
var y,root,w:longint;
begin
y:=x;
while p[y]>0 do
y:=p[y];
root:=y;
y:=x;
while p[y]>0 do
begin
w:=p[y];
p[y]:=root;
y:=w;
end;
find:=root;
end;
procedure union(x,y:longint);
var u,v:longint;
begin
u:=find(x);
v:=find(y);
if u>v then
begin
u:=u xor v;
v:=u xor v;
u:=u xor v;
end;
if u<>v then
begin
p[v]:=u;
a[u,1]:=a[u,1]+a[v,1];
a[u,2]:=a[u,2]+a[v,2];
end;
end;
function max(x,y:longint):longint;
begin
if x>y then exit(x)
else exit(y);
end;
begin
readln(n,m,w);
for i:=1 to n do
for j:=1 to 2 do
read(a[i,j]);
for i:=1 to m do
begin
read(x,y);
union(x,y);
end;
for i:=1 to n do
begin
if find(i)=i then
begin
inc(k);
b[k]:=a[i,1];
c[k]:=a[i,2];
end;
end;
for i:=1 to k do
begin
for j:=w downto b[i] do
f[j]:=max(f[j],f[j-b[i]]+c[i]);
end;
write(f[w]);
end.