• [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 }
  • 相关阅读:
    第一章 数据集散地:数据库
    第六章 使用ADO.NET查询和操作数据
    第五章 使用ADO.NET访问数据库
    第四章 深入C#的String类
    IOS框架和服务
    一步步调试解决iOS内存泄漏
    app跳转
    iOS 视频直播
    学习心得
    iOS中FMDB的使用
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7612639.html
Copyright © 2020-2023  润新知