zoukankan      html  css  js  c++  java
  • P3252 [JLOI2012]树

    题目描述

    在这个问题中,给定一个值S和一棵树。在树的每个节点有一个正整数,问有多少条路径的节点总和达到S。路径中节点的深度必须是升序的。假设节点1是根节点,根的深度是0,它的儿子节点的深度为1。路径不必一定从根节点开始。

    输入格式

    第一行是两个整数N和S,其中N是树的节点数。 第二行是N个正整数,第i个整数表示节点i的正整数。 接下来的N-1行每行是2个整数x和y,表示y是x的儿子。

    输出格式

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

    简单的思路就是先构造一棵树,然后便利树,因为深度要递增,所以我们要从一个点不断的去找叶子节点。

     

    链式 前向星存图

     1 struct  node
     2 {
     3     int w;//代表这条边的边权数值;
     4     int e;//代表以这条边为结尾的点的下标值;
     5     int next;//表示与第i条边同起点的上一条边的存储位置
     6 }ed[maxn];
     7 int head [maxn];//用来存储边的位置    
     8 int tot =0;
     9 void add (int u,int v,int w)
    10     {
    11       ed[++tot].w=w;//表示第i条边的权职是多少
    12       ed[tot].e=v;//表示第i条边的终点
    13       ed[tot].next=head[u];//head[i]表示以i为起点最后一条边的存储位置
    14       head[u]=tot++;
    15 }

    因为这道题不涉及到权值的问题,所以我们就不作考虑。

    那这道题的链前就可以写为:

     

     1 struct node
     2 {
     3     int u;
     4     int v;
     5 }to[100000];
     6 void add(int x,int y)
     7 {
     8     to[++tot].u=head[x];//head[i]表示以i为起点最后一条边的存储位置
     9     to[tot].v=y;//表示i条边的终点,也就是所连的节点
    10     head[x]=tot;//一共所连的边数
    11 }

    遍历一棵树可以用dfs但是由于这道题的数据范围,我们还需要再加一个剪枝。

    如果当前节点和已经超过s,我们就不需要继续往下搜索了。

    搜索的时候,深度需要升序,我们只能往下找当前节点的子节点。

    但是这样还不够,就即使加了剪枝依然会t掉4个点,所以我加了一个小小的读入优化,就神奇的过辽!

    代码如下:

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 using namespace std;
     5 int a[100000];
     6 int st,ed;
     7 int read()
     8 {
     9     int x = 1,a = 0;
    10     char ch = getchar();
    11     while(ch < '0' || ch > '9'){
    12         if(ch == '-')x = -1;
    13         ch = getchar();
    14     }
    15     while(ch <= '9'&&ch >= '0'){
    16         a = a * 10 + ch - '0';
    17         ch = getchar();
    18     }
    19     return x*a;
    20 }
    21 struct node
    22 {
    23     int u;
    24     int v;
    25 }to[100000];
    26 int fa[100000],head[100000],x,y,n,s,tot=0,ans=0;
    27 void add(int x,int y)
    28 {
    29     to[++tot].u=head[x];
    30     to[tot].v=y;
    31     head[x]=tot;
    32 }
    33 void dfs(int x,int dis)
    34 {
    35     if (dis>s)
    36         return;
    37     if (dis==s)
    38     {
    39         ans++;
    40         return;
    41     }
    42     for (int i = head[x];i>0;i=to[i].u)
    43     {
    44         int nxt=to[i].v;
    45         if (fa[x]!=nxt)
    46             dfs(nxt,dis+a[nxt]);
    47     }
    48 }
    49 int main()
    50 {
    51     n = read();
    52     s = read();
    53     memset(head, -1, sizeof(head));
    54     for (int i = 1;i <= n;i++)
    55     {
    56         a[i] = read();
    57         fa[a[i]]=a[i];
    58     }
    59     for (int i = 1;i <= n-1;i++)
    60     {
    61         st=read();
    62         ed=read();
    63         add(st,ed);
    64         fa[ed]=st;
    65     }
    66     for (int i = 1;i <= n;i++)
    67     {
    68         dfs(i,a[i]);
    69     }
    70     cout<<ans<<endl;
    71     return 0;
    72 }

     

     

     

     

     

  • 相关阅读:
    31天重构学习笔记21. 合并继承
    31天重构学习笔记15. 移除重复内容
    31天重构学习笔记22. 分解方法
    31天重构学习笔记18. 使用条件判断代替异常
    31天重构学习笔记19. 提取工厂类
    31天重构学习笔记24. 分解复杂判断
    31天重构学习笔记17. 提取父类
    大型项目的发布部署:第一章:发布部署流程
    HDU 2036 改革春风吹满地 数学题
    HDU 2051 Bitset
  • 原文地址:https://www.cnblogs.com/very-beginning/p/12200444.html
Copyright © 2011-2022 走看看