第十一次总结

题目

https://www.luogu.com.cn/problem/P1455

思路:总体而言就是一个并查集加01背包问题,注意:我们在查找到父节点的时候,要将子节点的价值与重量全部放在父节点上,相当于将这一棵二叉树看作是一个大的物品,我们在打dp表的时候就就看父节点这个大的物品就可以了,而且我们在大dp表的时候不用用二维数组了

动态规划有一个后无效性原则:当前状态只于上一个有关,与上上一个无关

我们发现,在我们这个二维的dp表中,我们可以通过滚动数组的方式来进行压缩,

如果数据很大,需要的数组就很大,但是我们只需要上一个的最大价值就可以了

状态转移方程:

if(j>=w[i])

dp[j]=max(dp[j],dp[j-w[i]]+c[i])

也就是用一个一维数组就可以了

#include<bits/stdc++.h>
using namespace std;
int n,m,w;
#define maxn 10005
int dp[maxn];
int val[maxn],rmb[maxn],arr[maxn];
void init(){
	for(int i=1;i<=n;i++)
	arr[i]=i;
	return ;
}
int getf(int u)
{
	if(arr[u]==u)
	return u; 
	else
	arr[u]=getf(arr[u]);
	return arr[u];
}
void merge(int x,int y)
{
	int fx=getf(x);
	int fy=getf(y);
	if(fx!=fy)//注意要累加 
	{
		arr[fx]=fy;
		rmb[fy]+=rmb[fx];
		val[fy]+=val[fx];
	}
}
int main(){
	int x,y;
	cin>>n>>m>>w;
	init();	
	for(int i=1;i<=n;i++)
	cin>>rmb[i]>>val[i];
	for(int i=0;i<m;i++)
	{
		cin>>x>>y;
		merge(x,y);
	}
	for(int i=1;i<=n;i++)
	{
		if(arr[i]==i)
		{
			for(int j=w;j>=rmb[i];j--)
			dp[j]=max(dp[j],dp[j-rmb[i]]+val[i]);
		}
	}
	cout<<dp[w]<<endl;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值