1. 程式人生 > >洛谷 P3252 [JLOI2012]樹

洛谷 P3252 [JLOI2012]樹

back 一個 節點數 insert name net data- max problem

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。

思路:樹上前綴和或者是爆搜

#include<iostream>
#include<set>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define MAXN 100100
using namespace std;
set<int>se;
int n,s,tot,ans;
int sum[MAXN],w[MAXN],dad[MAXN];
int to[MAXN*2],head[MAXN*2],net[MAXN*2]; void add(int u,int v){ to[++tot]=v;net[tot]=head[u];head[u]=tot; } void dfs(int now){ sum[now]=sum[dad[now]]+w[now]; se.insert(sum[now]); if(se.find(sum[now]-s)!=se.end()) ans++; for(int i=head[now];i;i=net[i]) dfs(to[i]); se.erase(sum[now]); }
int main(){ scanf("%d%d",&n,&s); for(int i=1;i<=n;i++) scanf("%d",&w[i]); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); dad[y]=x; add(x,y); } se.insert(0); dfs(1); cout<<ans; }

洛谷 P3252 [JLOI2012]樹