![洛谷P3252 [JLOI2012]树 洛谷P3252 [JLOI2012]树](https://image.shishitao.com:8440/aHR0cHM6Ly9ia3FzaW1nLmlrYWZhbi5jb20vdXBsb2FkL2NoYXRncHQtcy5wbmc%2FIQ%3D%3D.png?!?w=700&webp=1)
题目描述
在这个问题中,给定一个值S和一棵树。在树的每个节点有一个正整数,问有多少条路径的节点总和达到S。路径中节点的深度必须是升序的。假设节点1是根节点,根的深度是0,它的儿子节点的深度为1。路径不必一定从根节点开始。
输入输出格式
输入格式:
第一行是两个整数N和S,其中N是树的节点数。 第二行是N个正整数,第i个整数表示节点i的正整数。 接下来的N-1行每行是2个整数x和y,表示y是x的儿子。
输出格式:
输出路径节点总和为S的路径数量。
输入输出样例
输入样例#1:
3 3
1 2 3
1 2
1 3
输出样例#1:
2
说明
对于100%数据,N<=100000,所有权值以及S都不超过1000。
题目大意:求树上连续一段深度递增的路径的点权和为s的条数
题解:dfs(i)以i为起点的路径有多少条
错因:理解错了 不能用记忆化搜索
数据水暴力可过
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define LL long long
#define maxn 100008
using namespace std; int n,s,sumedge;
int head[maxn],w[maxn];
long long ans; struct Edge{
int x,y,nxt;
Edge(int x=,int y=,int nxt=):
x(x),y(y),nxt(nxt){}
}edge[maxn]; void add(int x,int y){
edge[++sumedge]=Edge(x,y,head[x]);
head[x]=sumedge;
} LL dfs(int x,int sum){
if(sum>s)return ;
if(sum==s)return ;
long long js=;
for(int i=head[x];i;i=edge[i].nxt){
int v=edge[i].y;
js+=dfs(v,sum+w[v]);
}
return js;
} int main(){
scanf("%d%d",&n,&s);
for(int i=;i<=n;i++)scanf("%d",&w[i]);
for(int i=;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
for(int i=;i<=n;i++)if(w[i]==s)ans++;else ans+=dfs(i,w[i]);
cout<<ans<<endl;
return ;
}
树上前缀和
保存搜到i之前的祖先,累加权值,是否sum[i]-sum[祖先]=s,注意搜完时删掉祖先。
#include<iostream>
#include<cstdio>
#include<cstring>
#define maxn 100008
#define LL long long
using namespace std; int n,s,sumedge,cnt,js;
int head[maxn],w[maxn],dad[maxn],fa[maxn],sum[maxn];
LL ans; struct Edge{
int x,y,nxt;
Edge(int x=,int y=,int nxt=):
x(x),y(y),nxt(nxt){}
}edge[maxn]; void add(int x,int y){
edge[++sumedge]=Edge(x,y,head[x]);
head[x]=sumedge;
} void dfs(int x){
dad[++js]=x;
for(int i=head[x];i;i=edge[i].nxt){
int v=edge[i].y;
sum[v]=sum[x]+w[v];
for(int j=js;j>=;j--){//要循环到0,可能它自己的点权就是s
if(sum[v]-sum[dad[j]]==s)ans++;
if(sum[v]-sum[dad[j]]>s)break;
}
dfs(v);
}
js--;
} int main(){
scanf("%d%d",&n,&s);
for(int i=;i<=n;i++)scanf("%d",&w[i]);
for(int i=;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
fa[y]=x;
add(x,y);
}
sum[]=w[];
dfs();
cout<<ans<<endl;
return ;
}