[洛谷P3252] [JLOI2012] 樹
阿新 • • 發佈:2020-08-07
[洛谷P3252] [JLOI2012] 樹
給定一個值\(S\)和一棵樹。在樹的每個節點有一個正整數,問有多少條路徑的節點總和達到\(S\)。
路徑中節點的深度必須是升序的。假設節點\(1\)是根節點,根的深度是\(0\),它的兒子節點的深度為\(1\)。
路徑不必一定從根節點開始。Input
第一行是兩個整數\(N\)和\(S\),其中\(N\)是樹的節點數。
第二行是\(N\)個正整數,第\(i\)個整數表示節點\(i\)的正整數。
接下來的\(N-1\)行每行是\(2\)個整數\(x\)和\(y\),表示\(y\)是\(x\)的兒子。Output
輸出路徑節點總和為\(S\)
的路徑數量。Example
輸入 #1
\(3\) \(3\)
\(1\) \(2\) \(3\)
\(1\) \(2\)
\(1\) \(3\)輸出 #1
\(2\)
Scoring
對於\(100%\)資料,\(N≤100000\),所有權值以及\(S\)都不超過\(1000\)。
注意:是總和剛好為\(S\),不是\(≥S\)
剛開始審題看成\(≥S\)了orz
咱也不會啥高階做法,暴力。
盲猜權值無負數,這樣的話選一個點,往下搜,搜到大於\(S\)就return,剛好等於\(S\)就ans++
期望複雜度\(O(nlogn)\),資料很水,沒有鏈,不會卡成\(O(n^2)\)。
程式碼:
#include<bits/stdc++.h> using namespace std; int n, s, x, y, cnt; int v[100005]; int fa[100005]; vector <int> p[100005]; void dfs(int pl, int sum) { sum += v[pl]; if (sum > s) return; if (sum == s) {cnt++; return;} for (int i = 0; i < p[pl].size(); i++) { if (p[pl][i] != fa[pl]) dfs(p[pl][i], sum); } } int main() { scanf("%d %d", &n, &s); for (int i = 1; i <= n; i++) scanf("%d", &v[i]); for (int i = 1; i < n; i++) { scanf("%d %d", &x, &y); fa[y] = x; p[x].push_back(y); } for (int i = 1; i <= n; i++) dfs(i, 0); printf("%d", cnt); return 0; }