P3252 [JLOI2012]树
Posted very-beginning
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
以上是关于P3252 [JLOI2012]树的主要内容,如果未能解决你的问题,请参考以下文章