1387:搭配购买(buy)
时间限制: 1000 ms 内存限制: 65536 KB
【题目描述】
Joe觉得云朵很美,决定去山上的商店买一些云朵。商店里有n朵云,云朵被编号为1,2,…,n,并且每朵云都有一个价值。但是商店老板跟他说,一些云朵要搭配来买才好,所以买一朵云则与这朵云有搭配的云都要买。
但是Joe的钱有限,所以他希望买的价值越多越好。
【输入】
第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。
【输出】
一行,表示可以获得的最大价值。
【输入样例】
5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2
【输出样例】
1
【提示】
【数据范围】
30%的数据保证:n≤100;
50%的数据保证:n≤1,000;m≤100;w≤1,000;
100%的数据保证:n≤10,000;0≤m≤5000;w≤10,000。
思路:并查集+01揹包,并查集将搭配云彩都整合,01揹包进行获取最大值。
#include<cstdio>
#include<iostream>
#include<cstring>
const int maxn = 1e4 + 5;
using namespace std;
int p[maxn],price[maxn],value[maxn],dp[maxn];
int find( int k){
while(k != p[k]) k = p[k];
return k;
}
void un(int a, int b){
int fa = find(a);
int fb = find(b);
if(fa != fb){
p[fa] = fb;
price[fb] += price[fa];
value[fb] += value[fa];
}
}
int main(){
int n,m,w,a,b,maxx = 0;
cin >> n >> m >>w;
for(int i = 1; i <= n; i++)
p[i] = i;
for(int i = 1; i <= n; i++)
{
cin >> price[i] >> value[i];
}
while(m--)
{
cin >> a >> b;
un(a,b);
}
for(int i = 1; i <= n; i++)
{
if(i == find(i)){
for(int v = w; v >= price[i];v--){
dp[v] = max(dp[v],dp[v-price[i]] + value[i]);
if(dp[v] > maxx) maxx = dp[v];
}
}
}
cout << maxx;
return 0;
}