题目描述
J o e Joe Joe 觉得云朵很美,决定去山上的商店买一些云朵。商店里有 n n n 朵云,云朵被编号为 1 , 2 , … . . . , n 1,2,…...,n 1,2,…...,n ,并且每朵云都有一个价值。但是商店老板跟他说,一些云朵要搭配来买才好,所以买一朵云则与这朵云有搭配的云都要买。但是 J o e Joe Joe 的钱有限,所以他希望买的价值越多越好。
输入格式
第
1
1
1 行
n
,
m
,
w
n,m,w
n,m,w ,表示
n
n
n 朵云,
m
m
m 个搭配,
J
o
e
Joe
Joe 有
w
w
w 的钱。
第
2
∼
n
+
1
2 \sim n + 1
2∼n+1 行,每行
c
i
,
d
i
c_i,d_i
ci,di 表示
i
i
i 朵云的价钱和价值。
第
n
+
2
∼
n
+
m
+
1
n + 2 \sim n + m + 1
n+2∼n+m+1 行,每行
u
i
,
v
i
u_i,v_i
ui,vi ,表示买
u
i
u_i
ui 就必须买
v
i
v_i
vi,同理,如果买
v
i
v_i
vi 就必须买
u
i
u_i
ui。
输出格式
一行,表示可以获得的最大价值。
样例
样例输入1:
5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2
样例输出1:
1
数据范围
30
%
30\%
30% 的数据保证:
n
≤
100
n \le 100
n≤100。
50
%
50\%
50% 的数据保证:
n
≤
1000
,
m
≤
100
,
w
≤
1000
n \le 1000,m \le 100,w \le 1000
n≤1000,m≤100,w≤1000。
100
%
100\%
100% 的数据保证:
n
≤
10
,
000
,
0
≤
m
≤
5000
,
w
≤
10
,
000
n \le 10,000,0 \le m \le 5000,w \le 10,000
n≤10,000,0≤m≤5000,w≤10,000。
题解
由于买了
c
i
c_i
ci 就必须买
d
i
d_i
di,所以可以把它们打包在一起,再按正常的 背包dp
做就行了。
维护可以使用并查集,如果不知道可以去搜索。
#include<bits/stdc++.h>
using namespace std;
int n, m, w;
int a[10010], b[10010];
int f[10010];
int dp[10010];
//并查集查找
int find(int x){
if(x == f[x]){
return x;
}
return f[x] = find(f[x]);
}
int main(){
输入 n, m, w, ai, bi
//初始并查集
for(int i = 1; i <= n; ++ i){
f[i] = i;
}
for(int i = 1; i <= m; ++ i){
int x, y;
scanf("%d %d", &x, &y);
int t1 = find(x), t2 = find(y);
f[t1] = t2;
}
//打包
for(int i = 1; i <= n; ++ i){
int t = find(i);
if(i != t){
a[t] += a[i];
a[i] = 0;
b[t] += b[i];
b[i] = 0;
}
}
//正常背包 dp
for(int i = 1; i <= n; ++ i){
for(int j = w; j >= a[i]; -- j){
dp[j] = max(dp[j], dp[j - a[i]] + b[i]);
}
}
printf("%d", dp[w]);
return 0;
}