搜索練習2
阿新 • • 發佈:2017-11-19
題目 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> #includeAC<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) return0; 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; }
自己選的路,跪著也要走完!!!
搜索練習2