首页 > 其他分享 >[笔记]树形dp

[笔记]树形dp

时间:2024-05-04 11:12:52浏览次数:21  
标签:int pos 笔记 vis 树形 dfs 节点 dp

树形dp,是一种建立在树形结构上的dp,因此dfs一般是实现它的通用手段。
是一种很美的动态规划呢。

P1352 没有上司的舞会

P1352 没有上司的舞会

在一棵树中,找到若干个互相独立(即互相没有边直接相连)的点,使它们的权值和最大。

我们发现,间隔选择的方法(只选深度为奇数/偶数的点)是不可行的。一个很简单的反例是这棵树是一条链:10 <-> 3 <-> 3 <-> 10,显然选择\(1,4\)才是正确的。

那么我们该怎么做呢?我们可以dfs遍历这棵树,对于一个节点,我们考虑两种选择情况:

  • 选当前节点:那么子节点就不能选。当前权值为所有子节点不选状态下的答案和。
  • 不选当前节点:那么子节点可以选,也可以不选。当前答案为所有子节点两种状态下的最大值之和。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,happy[6010];
vector<int> ch[6010];
bool b[6010];
int mem[6010][2];
int dfs(int pos,bool is){
	if(mem[pos][is]) return mem[pos][is];
	int ans=0,len=ch[pos].size();
	if(is){//如果上司去,则员工必须不去
		for(int i=0;i<len;i++) ans+=dfs(ch[pos][i],0);
		ans+=happy[pos]*(happy[pos]>0);
	}else{//如果上司不去,则员工有两种选择
		for(int i=0;i<len;i++) ans+=max(dfs(ch[pos][i],0),dfs(ch[pos][i],1));
	}
	return mem[pos][is]=ans;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>happy[i];
	for(int i=1;i<n;i++){
		int x,y;
		cin>>x>>y;
		b[x]=1;
		ch[y].push_back(x);
	}
	for(int i=1;i<=n;i++){
		if(!b[i]){
			cout<<max(dfs(i,0),dfs(i,1));
			break;
		}
	}
	return 0;
}

UVA1292 Strategic game

UVA1292 Strategic game

在一棵树中,找到若干个点,每个点放置\(1\)个士兵,每个士兵可以看守所在点邻接的所有边,现在我们想知道:要看守这棵树的所有边,最少需要多少士兵。

对于每个节点,考虑其选择情况:

  • 该节点放士兵:那么子节点可以放,也可以不放。取每个子节点放/不放的最小值求和即可。
  • 该节点不放士兵:那么子节点必须全放。取每个子节点放的和即可。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n;
vector<int> G[1510];
int f[1510][2];
bool vis[1510];
void dfs(int pos){
	f[pos][1]=1;
	for(auto i:G[pos]){
		dfs(i);
		f[pos][0]+=f[i][1];//如果当前不选,那么子节点必须全选
		f[pos][1]+=min(f[i][0],f[i][1]);//如果当前选,则选最小
	}
}
int main(){
	while(~scanf("%d",&n)){
		memset(f,0,sizeof f);
		memset(vis,0,sizeof vis);
		for(int i=1;i<=n;i++) G[i].clear();
		for(int i=1;i<=n;i++){
			int pos,m,num;
			scanf("%d:(%d)",&pos,&m);
			pos++;
			for(int j=1;j<=m;j++){
				cin>>num;
				num++;
				G[pos].push_back(num);
				vis[num]=1;
			}
		}
		int awa=-1;
		for(int i=1;i<=n;i++){
			if(!vis[i]){
				awa=i;
				break;
			}
		}
		dfs(awa);
		cout<<min(f[awa][0],f[awa][1])<<endl;
	}
	return 0;
}

P1122 最大子树和

P1122 最大子树和

在一棵树中选择一块联通分量,让其点权和最大。

用\(f[i]\)表示以\(i\)为根节点子树的答案。显然它的值就是子节点答案中,非负答案的和。

最后遍历\(f\)求出最大值即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,v[16010];
vector<int> G[16010];
bool vis[16010];
int f[16010];
void dfs(int pos){
	vis[pos]=1;
	f[pos]=v[pos];
	for(auto i:G[pos]){
		if(vis[i]) continue;
		dfs(i);
		if(f[i]>0) f[pos]+=f[i];
	}
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++) cin>>v[i];
	for(int i=1;i<n;i++){
		int u,v;
		cin>>u>>v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	dfs(1);
	int ans=INT_MIN;
	for(int i=1;i<=n;i++) ans=max(ans,f[i]);
	cout<<ans;
	return 0;
}

标签:int,pos,笔记,vis,树形,dfs,节点,dp
From: https://www.cnblogs.com/Sinktank/p/18171654

相关文章

  • #交互,dp#洛谷 7998 [WFOI - 01] 猜数(guess)
    题目传送门分析首先要搞清楚,交互库的自适应会让区间长度尽可能增大(答案自适应)也就是说,如果现在区间为\([l,r]\),你选取的区间为\([l',r']\),那么交互库会让你的区间变成\([l,r'-1]\)和\([l'+1,r]\)中区间更长的那一个,不妨枚举这个长度设\(dp[i]\)表示区间长度为\(i\)......
  • DP Record
    从2024/5/4往后开始记录捏。T1.给你一棵树,定义一个集合的权值为\(\dfrac{\sum_{x\inS}V_x}{\sum_{x\inS}C_x}\)。若一个点\(\inS\),则其父亲也必须\(\inS\)并且\(|S|=k\)。求满足条件的所有集合的最大价值。\(n,k\le2500\)。Solution:注意到那一个奇妙的式子......
  • 多项式模板学习笔记
    多项式乘法存在多项式\(F(z)=\sum_{i=0}^na_iz^i,G(z)=\sum_{i=0}^mb_iz^i\),我们定义多项式乘法:\[F(z)*G(z)=\sum_i\sum_ja_ib_jz^{i+j}\]多项式的点值表达一个\(n\)次函数可以用平面上的\(n+1\)个点来表达。所以我们可以把一个\(n\)次多项式从系数表达转化成\(n+......
  • ffmpeg常用API笔记
    1.ffmpeg日志系统<libavutil/log.h>1)av_log_set_level(AV_LOG_DEBUG)2)av_log(NULL,AV_LOG_INFO,"fmt...",op) 2.<libavformat/avformat.h>操作目录:1)avio_open_dir()打开一个目录。结构体AVIODirContext,表示目录的上下文信息。//参数1:上下文;参数2:要访问的目录的ur......
  • m基于LDPC编译码的matlab误码率仿真,对比SP,MS,NMS以及OMS四种译码算法
    1.算法仿真效果matlab2022a仿真结果如下:    2.算法涉及理论知识概要       低密度奇偶校验码(LDPC)译码是现代通信系统中一种高效的错误校正技术,广泛应用于无线通信、卫星通信和数据存储等领域。LDPC码因其良好的纠错性能和接近香农极限的潜力而受到重视。本文......
  • 算法基础课笔记
    二分整数二分有单调性一定可以二分,二分不一定有单调性数的范围intmain(){scanf("%d%d",&n,&m);for(inti=0;i<n;i++)scanf("%d",&q[i]);while(m--){intx;scanf("%d",&x);intl......
  • 时间序列预测模型对比——视频笔记
    Autoformer他的特点是加入了自动相关,代替原来的自注意力机制,因为作者认为数据不能简单由数值来判断,而应该根据趋势来判断。他与Dlinear一样,都是用到了decomposition,这个拆分(快速傅里叶变换FFT)基于STL(季节性,趋势性),数据=趋势性数据+季节性数据(周期)+余项auto-correlation代替注意力......
  • uboot-uboot介绍-学习笔记
    源码目录编译配置......
  • WPF Datagrid DataGridComboBoxColumn ObjectDataProvider ObjectDataProvider.Method
    //xaml<Windowx:Class="WpfApp90.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.mic......
  • uboot-学习笔记
    uboot引导程序的作用不同bootloader的对比系统启动自举过程阶段iROM读取流程......