[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 }

 

posted @ 2017-09-29 20:16  Z-Y-Y-S  阅读(266)  评论(0编辑  收藏  举报