[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。
遍历一遍,将根到当前节点路径上的所有的点的树上前缀和压入栈中。
查找时二分栈即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<set> 6 using namespace std; 7 struct Node 8 { 9 int next,to; 10 }edge[200001]; 11 int num,head[100001]; 12 int S[100001],top,sum[100001],val[100001],ans,n,s; 13 int fa[100001]; 14 void add(int u,int v) 15 { 16 num++; 17 edge[num].next=head[u]; 18 head[u]=num; 19 edge[num].to=v; 20 } 21 bool find(int x) 22 { 23 int l=0,r=top; 24 while (l<=r) 25 { 26 int mid=(l+r)/2; 27 if (S[mid]==x) return 1; 28 if (S[mid]>x) r=mid-1; 29 else l=mid+1; 30 } 31 return 0; 32 } 33 void dfs(int x) 34 {int i; 35 sum[x]=sum[fa[x]]+val[x]; 36 S[++top]=sum[x]; 37 if (find(sum[x]-s)) ans++; 38 for (i=head[x];i;i=edge[i].next) 39 { 40 int v=edge[i].to; 41 dfs(v); 42 } 43 top--; 44 } 45 int main() 46 {int i,u,v; 47 cin>>n>>s; 48 for (i=1;i<=n;i++) 49 scanf("%d",&val[i]); 50 for (i=1;i<=n-1;i++) 51 { 52 scanf("%d%d",&u,&v); 53 add(u,v); 54 fa[v]=u; 55 } 56 dfs(1); 57 cout<<ans; 58 }