P1455

搭配购买

题目描述

明天就是母亲节了,电脑组的小朋友们在忙碌的课业之余挖空心思想着该送什么礼物来表达自己的心意呢?听说在某个网站上有卖云朵的,小朋友们决定一同前往去看看这种神奇的商品,这个店里有 \(n\) 朵云,云朵已经被老板编号为 \(1,2,3,...,n\),并且每朵云都有一个价值,但是商店的老板是个很奇怪的人,他会告诉你一些云朵要搭配起来买才卖,也就是说买一朵云则与这朵云有搭配的云都要买,电脑组的你觉得这礼物实在是太新奇了,但是你的钱是有限的,所以你肯定是想用现有的钱买到尽量多价值的云。

输入格式

第一行输入三个整数,\(n,m,w\),表示有 \(n\) 朵云,\(m\) 个搭配和你现有的钱的数目。

第二行至 \(n+1\) 行,每行有两个整数, \(c_i,d_i\),表示第 \(i\) 朵云的价钱和价值。

\(n+2\)\(n+1+m\) 行 ,每行有两个整数 \(u_i,v_i\)。表示买第 \(u_i\) 朵云就必须买第 \(v_i\) 朵云,同理,如果买第 \(v_i\) 朵就必须买第 \(u_i\) 朵。

输出格式

一行,表示可以获得的最大价值。

样例 #1

样例输入 #1

5 3 10
3 10
3 10
3 10
5 100
10 1
1 3
3 2
4 2

样例输出 #1

1

提示

对于 \(30\%\) 的数据,满足 \(1 \le n \le 100\)
对于 \(50\%\) 的数据,满足 \(1 \le n, w \le 10^3\)\(1 \le m \le 100\)
对于 \(100\%\) 的数据,满足 \(1 \le n, w \le 10^4\)\(0 \le m \le 5 \times 10^3\)

思路很简单 并查集维护联通 然后当作整体背包DP即可
细节
不要进行并查集merge时合并c[] d[] 我猜想原因应该是getfa要不断更新
等merge完了 后再进行c[] d[] 的合并
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
int n,m,w,c[10005],d[10005],fa[10005],f[10005],Rank[10005];
int getfa(int x)
{
	if(fa[x]==x)return x;
	return fa[x]=getfa(fa[x]);
}
void merge(int x,int y)
{
	int fx=getfa(x),fy=getfa(y);
	fa[fx]=fy;
}
signed main()
{
	ios::sync_with_stdio(false);
	cin>>n>>m>>w;
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=n;i++)cin>>c[i]>>d[i];
	for(int i=1;i<=m;i++)
	{
		int u,v;
		cin>>u>>v;
		int fu=getfa(u),fv=getfa(v);
		if(fu!=fv)merge(fu,fv);
	}
//	for(int i=1;i<=n;i++)cout<<getfa(i)<<" ";cout<<"\n";
	for(int i=1;i<=n;i++)
	{
		if(fa[i]!=i)
		{
			c[getfa(i)]+=c[i];
			c[i]=0;
			d[getfa(i)]+=d[i];
			d[i]=0;
		}
	}
	for(int i=1;i<=n;i++)
		for(int j=w;j>=c[i];j--)
			f[j]=max(f[j],f[j-c[i]]+d[i]);
	cout<<f[w]<<"\n";
	return 0;
}
posted @ 2023-01-11 17:21  PKU_IMCOMING  阅读(9)  评论(0)    收藏  举报