Description
小C得到了一棵树,这棵树每个点都有一个权值且1为根节点。无聊的小C又随机了一个权值s,现在他想知道这棵树上有多少条路径的节点权值总和恰好为s,且满足该路径中节点的深度必须是升序的。
Input
第一行是两个正整数n,s,接下来一行n个正整数,表示每个节点的权值。
接下来n-1行,每行包含两个正整数,表示树上的一条边。
Output
输出一个数,表示满足条件的路径数。
Sample Input
3 3
1 2 3
1 2
1 3
Sample Output
2
Hint
对于30%的数据,n<=1000.
对于100%的数据,n<=100000,s,节点权值<=1000.
做法:(数据随机的话暴力就好了。。。。)
正解:处理一个树上前缀和,用一个栈维护根节点到当前节点的路径序列,每次二分查找即可。
代码如下(暴力的):
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
struct arr
{
int to,next;
}f[200007];
int n,s,a[100007],ls[100007],fa[100007],ans;
bool v[100007];
void dfs(int x)
{
v[x]=1;
for (int i=ls[x];i;i=f[i].next)
if (!v[f[i].to])
{
dfs(f[i].to);
fa[f[i].to]=x;
}
}
void zhen_dfs(int x,int ss)
{
if (ss>s) return;
if (ss==s)
{
ans++;
return;
}
if (x==0) return;
zhen_dfs(fa[x],ss+a[x]);
}
int main()
{
scanf("%d%d",&n,&s);
for (int i=1;i<=n;i++)
scanf("%d",&a[i]);
int x,y,e=0;
for (int i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
e++;
f[e].to=y;
f[e].next=ls[x];
ls[x]=e;
e++;
f[e].to=x;
f[e].next=ls[y];
ls[y]=e;
}
dfs(1);
for (int i=1;i<=n;i++)
zhen_dfs(i,0);
cout<<ans;
}