1. 程式人生 > >搜索練習2

搜索練習2

題目 color 升序 fine ora col urn show 復制

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。

Solution:

  簡單dfs,

  操作一:檢查葉子節點是否能夠直接構成一條路並且價值為s

  操作二:對於不是葉子節點的節點,那麽我們就向下查找是否在路徑上有權值和為s的路徑,若存在ans+1

      dfs過程中,一旦權值和>s就不可能存在等於s的情況了,所以直接return

      如果權值和==s,答案+1,即return 1

      否則調用自身,尋找滿足上述條件的情況

Code:

技術分享圖片
#include<cstdio>
#include<cstring>
#include
<iostream> #define LL long long using namespace std; const int M = 100010; int n,s,a[M],pre[M*4],to[M*4],head[M],vis[M],edge_num,ans; void add(int u,int v) { pre[++edge_num]=head[u]; to[edge_num]=v; head[u]=edge_num; } LL dfs(int now,int value) { if(value>s) return
0; if(value==s) return 1; LL sum=0;//sum清空 for(int i=head[now]; i; i=pre[i]) { int v=to[i]; sum+=dfs(v,value+a[v]); } return sum; } int main() { scanf("%d%d",&n,&s); for(int i=1; i<=n; i++) scanf("%d",&a[i]); for(int i=1; i<n; i++) { int x,y; scanf("%d%d",&x,&y); add(x,y); } for(int i=1; i<=n; i++) { if(a[i]==s) ans++; else ans+=dfs(i,a[i]); } printf("%d\n",ans); return 0; }
AC

自己選的路,跪著也要走完!!!

搜索練習2