bzoj2783 树

Posted ccz181078

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2783 树相关的知识,希望对你有一定的参考价值。

第一行是两个整数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 树的主要内容,如果未能解决你的问题,请参考以下文章

bzoj2783: [JLOI2012]树

BZOJ 2783 树

BZOJ 2783 [JLOI2012]树

BZOJ2783[JLOI2012]树 DFS+栈+队列

bzoj2783: [JLOI2012]树

[bzoj2783][JLOI2012]树_树的遍历