[JLOI2012]樹
阿新 • • 發佈:2017-09-29
str -m ostream tro fin 升序 深度 col next
題目描述
在這個問題中,給定一個值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。
遍歷一遍,將根到當前節點路徑上的所有的點的樹上前綴和壓入棧中。
查找時二分棧即可。
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<set> 6 using namespace std; 7 struct Node 8 { 9 int next,to; 10 }edge[200001]; 11 int num,head[100001]; 12 int S[100001],top,sum[100001],val[100001],ans,n,s; 13 int fa[100001]; 14 void add(int u,int v) 15 { 16 num++; 17 edge[num].next=head[u]; 18 head[u]=num; 19 edge[num].to=v; 20 } 21 bool find(int x) 22 { 23 int l=0,r=top; 24 while (l<=r) 25 { 26 int mid=(l+r)/2; 27 if (S[mid]==x) return 1; 28 if (S[mid]>x) r=mid-1; 29 else l=mid+1; 30 } 31 return 0; 32 } 33 void dfs(int x) 34 {int i; 35 sum[x]=sum[fa[x]]+val[x]; 36 S[++top]=sum[x]; 37 if (find(sum[x]-s)) ans++; 38 for (i=head[x];i;i=edge[i].next) 39 { 40 int v=edge[i].to; 41 dfs(v); 42 } 43 top--; 44 } 45 int main() 46 {int i,u,v; 47 cin>>n>>s; 48 for (i=1;i<=n;i++) 49 scanf("%d",&val[i]); 50 for (i=1;i<=n-1;i++) 51 { 52 scanf("%d%d",&u,&v); 53 add(u,v); 54 fa[v]=u; 55 } 56 dfs(1); 57 cout<<ans; 58 }
[JLOI2012]樹