码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj2783 树

时间:2016-05-16 19:35:48      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:

第一行是两个整数N和S,其中N是树的节点数。

第二行是N个正整数,第i个整数表示节点i的正整数。

接下来的N-1行每行是2个整数x和y,表示y是x的儿子。

输出格式:

输出路径节点总和为S的路径数量。

 

输入样例:

输出样例:

3 3

1 2 3

1 2

1 3

2

 

数据范围:

对于30%数据,N≤100;

对于60%数据,N≤1000;

对于100%数据,N≤100000,所有权值以及S都不超过1000。

倍增预处理出每个节点向上走2^k步到达的点和权值和,对每个点二分向上能走(权值和小于S)的距离

 

#include<cstdio>
inline int input(){
    int x=0,c=getchar();
    while(c>57||c<48)c=getchar();
    while(c>47&&c<58)x=x*10+c-48,c=getchar();
    return x;
}
const int N=100055;
int n,S,ans=0;
int vs[20][N],fa[20][N];
int main(){
    n=input();S=input();
    for(int i=1;i<=n;i++)vs[1][i]=input();
    for(int i=1,a,b;i<n;i++){
        a=input();b=input();
        fa[1][b]=a;
    }
    for(int t=1;t<19;t++){
        for(int i=1;i<=n;i++){
            int f=fa[t][i];
            fa[t+1][i]=fa[t][f];
            vs[t+1][i]=vs[t][f]+vs[t][i];
        }
    }
    for(int i=1;i<=n;i++){
        int s=S,w=i;
        for(int k=18;k;k--){
            int f=fa[k][w];
            if(!f)continue;
            if(vs[k][w]<s)s-=vs[k][w],w=f;
        }
        if(s==vs[1][w])++ans;
    }
    printf("%d\n",ans);
    return 0;
}

 

bzoj2783 树

标签:

原文地址:http://www.cnblogs.com/ccz181078/p/5499139.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!