AcWing 1252. 搭配购买
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。
输出格式
一行,表示可以获得的最大价值。
数据范围
1≤n≤10000,
0≤m≤5000,
1≤w≤10000,
1≤ci≤5000,
1≤di≤100,
1≤ui,vi≤n
输入样例:
5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2
输出样例:
1
刚开始的时候我觉得这道题非常简单,把一个集合的所有价值和钱数放到父节点上,然后我们去枚举小于等于w的父节点种哪个价值最大。
刚开始的代码如下。
#include<iostream>
#include<algorithm>using namespace std;const int N=1e4+10;int p[N],wi[N],ci[N];
bool st[N];int find(int x)
{
if(x==p[x]) return p[x];return p[x]=find(p[x]);}int main(void)
{
int n,m,w;cin>>n>>m>>w;for(int i=1;i<=n;i++) cin>>ci[i]>>wi[i];for(int i=1;i<=n;i++) p[i]=i;while(m--){
int a,b;cin>>a>>b;int pa=find(a),pb=find(b);if(pa!=pb){
ci[pa]+=ci[pb];wi[pa]+=wi[pb];p[pb]=pa;st[pb]=true;}}int res=0;for(int i=1;i<=n;i++)if(!st[i]){
if(w>=ci[i])res=max(res,wi[i]);}cout<<res<<endl;
}
然后我的样例是过了,但是我很疑惑我的思路没有什么错误为什么没有AC呢,我推敲了一下我的代码,基本上按我的逻辑进行的,我无奈之下看了题解,才发现,最后枚举的时候是一个背包问题,我也是有点马虎,居然没发现这个细节,可见我是多么的菜。
代码AC版就出来了,还是要仔细分析题目。
#include<iostream>
#include<algorithm>using namespace std;const int N=1e4+10;int p[N],wi[N],ci[N];
bool st[N];
int f[N];int find(int x)
{
if(x==p[x]) return p[x];return p[x]=find(p[x]);}int main(void)
{
int n,m,w;cin>>n>>m>>w;for(int i=1;i<=n;i++) cin>>ci[i]>>wi[i];for(int i=1;i<=n;i++) p[i]=i;while(m--){
int a,b;cin>>a>>b;int pa=find(a),pb=find(b);if(pa!=pb){
ci[pa]+=ci[pb];wi[pa]+=wi[pb];p[pb]=pa;}}for(int i=1;i<=n;i++)if(p[i]==i&&w>=ci[i]){
for(int j=w;j>=ci[i];j--)f[j]=max(f[j],f[j-ci[i]]+wi[i]);}cout<<f[w];
}