洛谷——P3252 [JLOI2012]树

时间:2024-04-15 03:55:47

P3252 [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。

zz,才开时的时候读错题目了,然后数组内存的与我要存的不一样,结果我竟然忘记改了!!傻不拉几的交了6遍,发现全部零分、、、

for循环,dfs找一每一个点往下的路径,超时

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 210000
using namespace std;
bool vis[N];
int n,m,x,y,ans,tot,root;
int  a[N],fa[N],sum[N],deep[N],head[N];
int read()
{
    ,f=; char ch=getchar();
    ; ch=getchar();}
    +ch-'; ch=getchar();}
    return x*f;
}
struct Edge
{
    int to,next,from;
}edge[N<<];
int add(int x,int y)
{
    tot++;
    edge[tot].to=y;
    edge[tot].next=head[x];
    head[x]=tot;
}
int dfs(int x)
{
    sum[x]=sum[fa[x]]+a[x];
    for(int i=head[x];i;i=edge[i].next)
    {
        int to=edge[i].to;
        if(!vis[to]&&fa[x]!=to)
        {
            vis[to]=true;
            dfs(to);
            vis[to]=false;
        }
    }
}
int main()
{
    n=read(),m=read();
    ;i<=n;i++)
     a[i]=read();
    ;i<n;i++)
    {
        x=read(),y=read();
        add(x,y);fa[y]=x;
     }
    ;i<=n;i++)
    {
        memset(sum,,sizeof(sum));
        dfs(i);
        ;i<=n;i++)
        if(sum[i]==m)  ans++;
      }
    printf("%d",ans);
    ;
}

TLE的dfs

依旧是dfs,不过我们不是以每一个点为根节点进行搜索,而是在dfs到每一个点的时候,我们以每一个点为叶子节点,然后向上搜索,判断路径长度是否已经到达m,我们要在向上搜的时候搜到根节点便停止搜索,防止在while中死循环!

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 210000
using namespace std;
bool vis[N];
int n,m,x,y,ans,tot,sum,root;
int  a[N],fa[N],deep[N],head[N];
int read()
{
    ,f=; char ch=getchar();
    ; ch=getchar();}
    +ch-'; ch=getchar();}
    return x*f;
}
struct Edge
{
    int to,next,from;
}edge[N<<];
int add(int x,int y)
{
    tot++;
    edge[tot].to=y;
    edge[tot].next=head[x];
    head[x]=tot;
}
int pd(int x)
{
    sum=a[x];
    while(sum<m)
    {
        sum+=a[fa[x]],x=fa[x];
        if(!fa[x]) break;
    }
    if(sum==m) return true;
    return false;
}
int dfs(int x)
{
    for(int i=head[x];i;i=edge[i].next)
    {
        int to=edge[i].to;
        if(!vis[to]&&fa[x]!=to)
        {
            vis[to]=true;
            if(pd(to)) ans++;
            pd(to),dfs(to);
            vis[to]=false;
        }
    }
    return ans;
}
int main()
{
    n=read(),m=read();
    ;i<=n;i++)
     a[i]=read();
    ;i<n;i++)
    {
        x=read(),y=read();
        add(x,y);fa[y]=x;
     }
    ;i<=n;i++)
     if(!fa[i]) root=i;
    dfs(root);
    printf("%d",ans);
    ;
}