首页 > 编程语言 >算法随笔——高级树形DP

算法随笔——高级树形DP

时间:2024-08-06 15:17:07浏览次数:13  
标签:int siz son 树形 DP 随笔 节点 dp define

换根DP学习博客
https://www.luogu.com.cn/article/wdk0q56f

树上背包

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

简单题意

叶子节点有权值,每条边有花费,问最多连接多少个叶子节点到根,使得权值总和大于花费总和。

做法

设 \(dp_{i,x,j}\) 为在第 x 个节点,使用前 i 个子节点的子树,选j个最大能获得的钱数。

答案就为 最大的 j 使得 \(dp_{i,x,j}\) 非负。

考虑转移

\[\huge dp_{i,x,j} = \max \{ {dp_{i-1,x,j-k} + dp_{siz(son),son,k} - w_{x,son} } \} \]

这是一个分组背包,每个子节点都是一个组,通过背包的经验,可以将 i 这一维滚动掉。
于是就没了。
注意枚举 k 时不能超过 j,也不能超过当前子节点的 size,这一细节可以优化成 \(O(N^2)\) 的复杂度。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define INF 0x3f3f3f3f
#define re register
#define PII pair<int,int>
int read()
{
	int f=1,k=0;char c = getchar();
	while(c <'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9')k=(k<<1)+(k<<3)+(c^48),c=getchar();
	return k*f;
}

const int N = 4005;

int n,m;
vector<PII> v[N];

int c[N];
//dp[i][x][j] 表示在第 x 个节点,使用前 i 个子节点的子树,选j个最大能获得的钱数。
int dp[N][N]; 
int siz[N];

void dfs(int x)
{
	if (x >= n-m+1)
	{ //判断为叶子节点
		siz[x] = 1;
		dp[x][1] = c[x]; //选一个为自己
		return;
	}
	for (int i = 0;i < v[x].size();i++) //根据分组背包,先枚举组别
	{
		auto [y,w] = v[x][i];
		dfs(y);
		siz[x] += siz[y];
		//为了滚动,倒序枚举
		for (int j = siz[x];j >= 0;j--) //前 i 个j上界为当前的size
		{
			for (int k = 0;k <= siz[y];k++) //枚举决策
			{
				if (k > j) break;
				dp[x][j] = max(dp[x][j],dp[x][j-k] + dp[y][k] - w);
			}
		}
	}
}

int main()
{
	memset(dp,-INF,sizeof dp);
	cin >> n >> m;
	for (int i = 1;i <= n-m;i++) 
	{
		int k = read();
		for (int j = 1;j <= k;j++)
		{
			int x = read(),c= read();
			v[i].push_back({x,c});	
		}
		dp[i][0] = 0; //初始化,选0个代价为0
	}
	
	for (int i = 1;i <= m;i++) c[i+n-m] = read();
	
	dfs(1);
	
	for (int k = m;k >= 0;k--)
	{
		if (dp[1][k] >= 0)
		{
			cout << k << endl;
			return 0;
		}
	}
	return 0;
}

标签:int,siz,son,树形,DP,随笔,节点,dp,define
From: https://www.cnblogs.com/codwarm/p/18343995

相关文章

  • CF1993D-二分+dp处理中位数
    CF1993D-二分+dp处理中位数大致题意给定两个正整数n和k以及另一个由n个整数组成的数组a。在一次操作中,可以选择a的任意一个大小为k的子数组,然后将其从数组中删除,而不改变其他元素的顺序。更正式地说,假设$(l,r)$是对子数组\(a_l,a_{l+1},…,a_r\)的操作,使得\(r......
  • 动态规划之——背包DP(入门篇)
    文章目录概要说明01背包模板例题题意概要思路code1code201背包的应用题题目来源思路code完全背包模板例题题意概要思路code概要说明本文只讲了01背包和完全背包,至于其他背包问题后续补充01背包模板例题点击这里题意概要思路01背包的模板题首先对于背包问......
  • 换根 dp
    板子P2986[USACO10MAR]GreatCowGatheringGP3478[POI2008]STA-StationP3047[USACO12FEB]NearbyCowsG很好的一题f[i][j]表示与点i(向下(点i儿子1中的点))距离为j的点的权值和g[i][j]表示与点i(所有)距离为j的点的权值和需要特别注意的是刚开始时g[i][j]=......
  • 状态压缩DP
    状态压缩DP定义:‌状态压缩是一种使用二进制数来表示状态的方法,通常用于表示只有两种状态(0和1)的对象。Acwing,291蒙特里安的梦想291.蒙德里安的梦想-AcWing题库题目概览求把N×......
  • 算法随笔——欧拉回路
    学习链接oiwiki定义判别方法P7771【模板】欧拉路径(有向图)P7771【模板】欧拉路径#include<bits/stdc++.h>usingnamespacestd;#definelllonglong#defineINF0x3f3f3f3f#definereregister#definePIIpair<int,int>intread(){ intf=1,k=0;charc=get......
  • 常见CMS漏洞(WordPress、DeDeCMS、ASPCMS、PHPMyadmin、Pageadmin)
    目录一:WordPress步骤一:进入Vulhub靶场并执行以下命令开启靶场;在浏览器中访问并安装好子...步骤二:思路是修改其WP的模板写入一句话木马后门并访问其文件即可GetShel;登陆WP后点击【外观】--》【编辑】--》404.php步骤三:访问以下连接即可获取WebShel...姿势二:上传主......
  • Luogu P1777 帮助 题解 [ 紫 ] [ 线性 dp ] [ 状压 dp ]
    帮助:大毒瘤!!!调了我2h,拍了我2h,最后没调出来,重写才AC。wdnmd。思路这题主要是线性dp,而状压dp只是最后在统计答案时的一个辅助。首先定义\(dp[i][j][k]\)为考虑前\(i\)本书,已经抽出来了\(j\)本,最后没被抽出来的一本书是高度\(k\)的最小混乱度。每次放入的书与最后一位......
  • 简析传输层协议——TCP、UDP协议
    TCP/IP协议族的传输层协议TCP(TransmissionControlProtocol)传输控制协议UDP(UserDatagramProtocol)用户数据报协议TCP协议介绍:TCP是面向连接的、可靠的进程到进程通信的协议TCP提供全双工服务,即数据可在同一时间双向传输TCP报文段:TCP将若干个字节构成一个分......
  • AtCoder Beginner Contest 365 随笔
    擦,F假了A判断闰年B输出次大值的下标用pair排序后即可C给定一个数组\(A_n\)和整数\(M\),尝试找到一个最大的\(m\),使得:\[\sum_{i=1}^n\min(A_i,m)\leM\]不等号左边显然随着\(m\)的增大而增大,所以可以二分一个\(m\),然后判断即可D两个人玩\(n\)局剪刀石头布......