洛谷 P3252 [JLOI2012]树
题目描述
在这个问题中,给定一个值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。
思路:树上前缀和或者是爆搜
#include<iostream> #include<set> #include<cstdio> #include<cstring> #include<algorithm> #define MAXN 100100 using namespace std; set<int>se; int n,s,tot,ans; int sum[MAXN],w[MAXN],dad[MAXN]; int to[MAXN*2],head[MAXN*2],net[MAXN*2]; void add(int u,int v){ to[++tot]=v;net[tot]=head[u];head[u]=tot; } void dfs(int now){ sum[now]=sum[dad[now]]+w[now]; se.insert(sum[now]); if(se.find(sum[now]-s)!=se.end()) ans++; for(int i=head[now];i;i=net[i]) dfs(to[i]); se.erase(sum[now]); } int main(){ scanf("%d%d",&n,&s); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); dad[y]=x; add(x,y); } se.insert(0); dfs(1); cout<<ans; }
细雨斜风作晓寒。淡烟疏柳媚晴滩。入淮清洛渐漫漫。
雪沫乳花浮午盏,蓼茸蒿笋试春盘。人间有味是清欢。