本文主要是介绍1387:搭配购买(buy)(并查集+01背包),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
【题目描述】
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。
思路:
把搭配要买的整合到一起(在一般并查集合并的时候加上整合),每个独立的点集(f[v]==v)就是算是一个商品,最后用01背包求解
代码:
#include<iostream>
#include<string>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int n , m , cost;
int f[10005];
int w[10005] , v[10005] , kk[10005];//01背包求解时候用
struct sta
{int x , y;
}k[10005];
void init()//初始化
{for(int i = 1 ; i <= n ; i++){f[i] = i;}
}
int getf(int v)//找父亲
{if(f[v] == v) return v;else return getf(f[v]);
}
void merge1(int u , int v)
{int t1 = getf(u);int t2 = getf(v);if( t1 != t2){f[t2] = t1;//把要搭配的商品整合成一个商品k[t1].x += k[t2].x;k[t1].y += k[t2].y;}
}
int main()
{cin>>n>>m>>cost;init();for(int i = 1 ; i <= n ; i++){cin>>k[i].x>>k[i].y;}int x , y;for(int i = 1 ; i <= m ; i++){cin>>x>>y;merge1( x , y);//合并要搭配的商品}int tip = 0;for(int i = 1 ; i <= n ; i++){if(f[i] == i)//总共有几个可以买的商品{tip++;w[tip] = k[i].x;v[tip] = k[i].y;}}for(int i = 1 ; i <= tip ; i++)//01背包求解{for(int j = cost ; j >= w[i] ; j--)kk[j] = max(kk[j - w[i]] + v[i] , kk[j]);}cout<<kk[cost];
}
这篇关于1387:搭配购买(buy)(并查集+01背包)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!