题目
给定一个值S和一棵树。在树的每个节点有一个正整数,问有多少条路径的节点总和达到S。路径中节点的深度必须是升序的。假设节点1是根节点,根的深度是0,它的儿子节点的深度为1。路径不必一定从根节点开始。求路径节点总和为S的路径数量
分析
这道题可以用倍增做,用求LCA的方法,求出f数组,与此同时求出节点向上 2 x 2^x 2x的路径节点总和,然后扫描以某个节点为终点是否能求出答案
代码
#include <cstdio>
using namespace std;
int len[100001][17],f[100001][17],ans,n,s;
int in(){
int ans=0; char c=getchar();
while (c<48||c>57) c=getchar();
while (c>47&&c<58) ans=ans*10+c-48,c=getchar();
return ans;
}
int main(){
n=in(); s=in(); int x,y;
for (int i=1;i<=n;i++) len[i][0]=in();
for (int i=1;i<n;i++){x=in(),f[in()][0]=x;}
for (int j=1;j<17;j++)
for (int i=1;i<=n;i++){
f[i][j]=f[f[i][j-1]][j-1];//LCA
len[i][j]=len[i][j-1]+len[f[i][j-1]][j-1];
}
for (int i=1;i<=n;i++){
x=0; y=i;
for (int j=16;j>=0;j--){
if (len[y][j]+x<=s) x+=len[y][j],y=f[y][j];//可以向上跳
if (x==s) {ans++; break;}//找到答案
}
}
return !printf("%d",ans);
}
本文介绍了一种使用倍增法结合LCA求最远祖先的方法来解决给定树上路径节点和等于特定值的问题。通过预处理得到每个节点到其2^k个祖先的路径和,可以在O(logN)时间内查询任意节点作为终点时是否存在一条路径的节点之和等于给定值S。
275

被折叠的 条评论
为什么被折叠?



