当前位置: 首页 > news >正文

树形DP总结①

树形DP,顾名思义就是在树上DP

T1 B3861 子树和

首先使用数组sz来存储答案(代码中是dis因为sz被【数据删除】了)

可以发现要先算出子树的答案再算出根的答案,所以枚举顺序是自底向上

那么,对于每个点:

定义状态:sz[i]表示根为i的子树的答案

确定答案:sz[i]

状态转移:sz[i]+=sum(sz[i的子节点])

初始值&边界:sz[i]=1

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=1e6+5,mod=1e9+7,inf=1e18;
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
void write(int x){if(x<0){putchar('-'),x=-x;}if(x>9){write(x/10);}putchar(x%10+'0');return;}
int fpow(int a,int b,int p){if(b==0){return 1;}int res=fpow(a,b/2,p)%p;if(b%2==1){return((res*res)%p*a)%p;}else{return(res*res)%p;}}
int n;
int dis[maxn];
vector<int>vt[maxn];
void dfs(int x,int ff){dis[x]=1;for(int v:vt[x]){if(v==ff)continue;dfs(v,x);dis[x]+=dis[v];}
} 
signed main(){cin>>n;for(int i=2;i<=n;i++){int x;cin>>x;vt[i].push_back(x);vt[x].push_back(i);}dfs(1,0);int maxi=0;for(int i=1;i<=n;i++){cout<<dis[i]<<endl;}return 0;
}

T2 P1122 最大子树和

其实就是子树和这道题加了一个判断

如果根加上子树的答案比根的答案大就更新根的答案(跟子序列同理)

定义状态:dp[i]表示根为i的子树的答案

确定答案:max(dp[i])

状态转移:dp[i]=max(dp[i],dp[x]+dp[i的子节点])

初始值&边界:dp[i]=a[i]

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=1e6+5,mod=1e9+7,inf=1e18;
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
void write(int x){if(x<0){putchar('-'),x=-x;}if(x>9){write(x/10);}putchar(x%10+'0');return;}
int fpow(int a,int b,int p){if(b==0){return 1;}int res=fpow(a,b/2,p)%p;if(b%2==1){return((res*res)%p*a)%p;}else{return(res*res)%p;}}
int n;
int dp[maxn],val[maxn];
vector<int>vt[maxn];
void dfs(int x,int ff){dp[x]=val[x];for(int v:vt[x]){if(v==ff)continue;dfs(v,x);dp[x]=max(dp[x],dp[x]+dp[v]);}
} 
signed main(){cin>>n;for(int i=1;i<=n;i++){cin>>val[i];}for(int i=1;i<n;i++){int x,y;cin>>x>>y;vt[y].push_back(x);vt[x].push_back(y);}dfs(1,0);int maxi=-inf;for(int i=1;i<=n;i++){maxi=max(maxi,dp[i]);}cout<<maxi;return 0;
}

T3 P1352 没有上司的舞会

这里因为涉及选或不选,我们再加一个维度表示选或者不选

定义状态:dp[i][0/1]表示根为i的子树的答案

确定答案:max(dp[i][0],dp[i][1]),因为树无论怎么变,答案都不变,所以可以用1号店替代

状态转移:dp[i][0]+=max(dp[i的子节点][0],dp[i的子节点][1])

     dp[i][1]+=dp[i的子节点][0]

初始值&边界:dp[i][1]=a[i],dp[i][0]=0

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=1e6+5,mod=1e9+7,inf=1e18;
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
void write(int x){if(x<0){putchar('-'),x=-x;}if(x>9){write(x/10);}putchar(x%10+'0');return;}
int fpow(int a,int b,int p){if(b==0){return 1;}int res=fpow(a,b/2,p)%p;if(b%2==1){return((res*res)%p*a)%p;}else{return(res*res)%p;}}
int n;
int dp[maxn][2],val[maxn];
vector<int>vt[maxn];
void dfs(int x,int ff){dp[x][1]+=val[x];for(int v:vt[x]){if(v==ff)continue;dfs(v,x);dp[x][0]+=max(dp[v][0],dp[v][1]);dp[x][1]+=dp[v][0];}
} 
signed main(){cin>>n;for(int i=1;i<=n;i++){cin>>val[i];}for(int i=1;i<n;i++){int x,y;cin>>x>>y;vt[y].push_back(x);vt[x].push_back(y);}dfs(1,0);cout<<max(dp[1][0],dp[1][1]);return 0;
}

T4 P2016 战略游戏

与上一题类似,只是变成了最小值,但不同的是,就算父亲放了,儿子也可以放,但父亲没放,儿子就必须放

#include<bits/stdc++.h>
#define int long long
#define endl "\n"
using namespace std;
const int maxn=1e6+5,mod=1e9+7,inf=1e18;
int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0' && ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
void write(int x){if(x<0){putchar('-'),x=-x;}if(x>9){write(x/10);}putchar(x%10+'0');return;}
int fpow(int a,int b,int p){if(b==0){return 1;}int res=fpow(a,b/2,p)%p;if(b%2==1){return((res*res)%p*a)%p;}else{return(res*res)%p;}}
int n;
int dp[maxn][2],val[maxn];
vector<int>vt[maxn];
void dfs(int x,int ff){dp[x][1]=1;dp[x][0]=0;for(int v:vt[x]){if(v==ff)continue;dfs(v,x);dp[x][1]+=min(dp[v][0],dp[v][1]);dp[x][0]+=dp[v][1];}
} 
signed main(){memset(dp,0x3f3f3f3f,sizeof(dp));cin>>n;for(int i=1;i<=n;i++){int x,y,k;cin>>x>>y;while(y--){cin>>k;vt[k].push_back(x);vt[x].push_back(k);}}dfs(0,0);cout<<min(dp[0][0],dp[0][1]);return 0;
}
http://www.sczhlp.com/news/22390/

相关文章:

  • 线性代数(1):高斯消元与行列式
  • 职业发展规划
  • 建设中医知识学习网站seo全网优化推广
  • 网站建设 互成网络网上哪里接app推广单
  • wordpress导航模板下载做seo推广公司
  • 铁岭免费网站建设成人培训班有哪些课程
  • 互联网企业概念自然搜索优化
  • 临沂医院手机网站建设app拉新推广平台渠道商
  • 轻量级流程编排框架,Solon Flow v3.5.0 发布
  • pacman -Syu 命令的含义详解
  • 做网站个网站要多少钱seo网站收录工具
  • 大型电子商务网站开发架构国内最新十大新闻
  • 电商网站开发用什么软件好互动营销的概念
  • 魔站网站建设自己建立网站步骤
  • php网站建设一流程上海网站关键词排名优化报价
  • 建网站定制黑帽seo寄生虫
  • 成都品牌设计网站建站的公司
  • 丹东做网站公司武汉百度seo排名
  • 企业网站的总体设计软文广告怎么写
  • WordPress国外主机seo sem优化
  • 产品网站怎么做的厦门seo计费
  • 宝塔做两个网站站长工具seo综合查询工具
  • (bitset优化01背包)CF1917F Construct Tree
  • 在AI技术唾手可得的时代,挖掘新需求成为制胜关键——某知名轻量级GUI框架需求探索
  • 网站建设时间进度表模板百度快速seo
  • 网站设计维护合同如何优化关键词搜索排名
  • 贵阳手机网站开发seo优化网络
  • 前端只是做网站吗南宁优化推广服务
  • 企业平台是什么意思淘宝seo关键词的获取方法有哪些
  • 贵阳seo推广深圳网络优化公司