標籤:stl set
Description
在這個問題中,給定一個值S和一棵樹。在樹的每個節點有一個正整數,問有多少條路徑的節點總和達到S。路徑中節點的深度必須是升序的。假設節點1是根節點,根的深度是0,它的兒子節點的深度為1。路徑不必一定從根節點開始。
Input
第一行是兩個整數N和S,其中N是樹的節點數。 第二行是N個正整數,第i個整數表示節點i的正整數。 接下來的N-1行每行是2個整數x和y,表示y是x的兒子。
Output
輸出路徑節點總和為S的路徑數量。
Sample Input
3 3
1 2 3
1 2
1 3
Sample Output
2
HINT
對於100%資料,N≤100000,所有權值以及S都不超過1000。
由於路徑必須是深到淺的一條鏈
所以DFS+set維護出現過的值就行了
#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<algorithm>#include<set>#define MAXN 100010using namespace std;int n,s,top;int val[MAXN],dis[MAXN],fa[MAXN];int root;long long ans;multiset<int> S;struct edge{ int to; edge *next;}e[MAXN<<1],*prev[MAXN];void insert(int u,int v){ e[++top].to=v;e[top].next=prev[u];prev[u]=&e[top];}void dfs(int x){ for (edge *i=prev[x];i;i=i->next) { dis[i->to]=dis[x]+val[i->to]; S.insert(dis[i->to]); if (S.find(dis[i->to]-s)!=S.end()) ans++; dfs(i->to); S.erase(dis[i->to]); }}int main(){ scanf("%d%d",&n,&s);S.clear(); for (int i=1;i<=n;i++) scanf("%d",&val[i]); for (int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); fa[y]=x;insert(x,y); } for (int i=1;i<=n;i++) if (!fa[i]) root=i; dis[root]=val[root];S.insert(0);S.insert(val[root]); if (S.find(dis[root]-s)!=S.end()) ans++; dfs(root); printf("%lld\n",ans);}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
【JLOI2012】【BZOJ2783】樹