• bzoj 2783: [JLOI2012]树


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

    解题报告:
    用时20min,1AC
    这题找到了题面就简单了,因为题目要求路径深度要满足升序,所以直接把一个点的所有的父节点都压人栈中,然后二分到那个位置,如果存在这样的路径答案就加1

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    const int N=100005;
    int head[N],num=0,S,nxt[N<<1],to[N<<1],val[N],n,st[N],top=0,dis[N];
    void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
    bool check(int x){
       int l=0,r=top,mid;
       while(l<=r){
          mid=(l+r)>>1;
          if(dis[x]-dis[st[mid]]==S)return true;
          if(dis[x]-dis[st[mid]]<S)r=mid-1;
          else l=mid+1;
       }
       return false;
    }
    int ans=0;
    void dfs(int x,int last){
       int u;st[++top]=x;
       ans+=check(x);
       for(int i=head[x];i;i=nxt[i]){
          u=to[i];if(u==last)continue;
          dis[u]=dis[x]+val[u];
          dfs(u,x);
       }
       top--;
    }
    void work()
    {
       int x,y;
       scanf("%d%d",&n,&S);
       for(int i=1;i<=n;i++)scanf("%d",&val[i]);
       for(int i=1;i<n;i++){
          scanf("%d%d",&x,&y);
          link(x,y);link(y,x);
       }
       dis[1]=val[1];dfs(1,1);
       printf("%d
    ",ans);
    }
    
    int main()
    {
    	work();
    	return 0;
    }
    
    
  • 相关阅读:
    I Hate It
    hdu 2112 HDU Today ( Dijkstra )
    hdu 1280 前m大的数
    hdu 4252 A Famous City
    hdu 2647 Reward
    hdu 2845 Beans
    hdu 3548 Enumerate the Triangles ( 优 化 )
    hdu 3552 I can do it! (贪心)
    HDU 3033 I love sneakers!(分组背包变形)
    hdu 1712 ACboy needs your help 分组背包
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7608099.html
Copyright © 2020-2023  润新知