bzoj 2783 JLOI2012 树
2017-04-25 21:27
375 查看
bzoj2783 JLOI2012 树
Description
在这个问题中,给定一个值S和一棵树。在树的每个节点有一个正整数,问有多少条路径的节点总和达到S。路径中节点的深度必须是升序的。假设节点1是根节点,根的深度是0,它的儿子节点的深度为1。路径不必一定从根节点开始。Input
第一行是两个整数N和S,其中N是树的节点数。第二行是N个正整数,第i个整数表示节点i的正整数。
接下来的N-1行每行是2个整数x和y,表示y是x的儿子。
Output
输出路径节点总和为S的路径数量。参考了神犇的博客,可以用dfs加set过,这么打比某些方法要方便一些.我们记录下一条链的前缀和,把它放进set里面,对于当前搜到的点x,如果set里面有一个元素等于sum[x]-S,那么表示从根到x节点的和减去那个元素所对应的点的和就是S.开始的时候要加入元素0.
代码如下
#include <set> #include <cstdio> #include <algorithm> using namespace std; static const int maxm=1e6+10; multiset<int>Set; int fst[maxm],nxt[maxm],to[maxm],sum[maxm],val[maxm]; int S,cnt,n,x,y,ans; void ins(int f,int t){ nxt[++cnt]=fst[f]; fst[f]=cnt; to[cnt]=t; } void dfs(int x){ if(Set.find(sum[x]-S)!=Set.end())ans++; Set.insert(sum[x]); for(int u=fst[x];u;u=nxt[u]){ int v=to[u]; sum[v]=sum[x]+val[v]; dfs(v); } Set.erase(Set.find(sum[x])); } int main(){ scanf("%d%d",&n,&S); for(int i=1;i<=n;i++)scanf("%d",&val[i]); for(int i=1;i<n;i++) scanf("%d%d",&x,&y),ins(x,y); sum[1]=val[1];Set.insert(0); dfs(1); printf("%d\n",ans); return 0; }
点我进入AC通道
相关文章推荐
- 【bzoj2783】【JLOI2012】【树】【set】
- 【BZOJ 2783】 [JLOI2012]树
- 【BZOJ2783】[JLOI2012]树 DFS+栈+队列
- BZOJ 2783 JLOI2012 树 二分 + 倍增
- BZOJ 2783 JLOI 2012 树 倍增+二分
- 【BZOJ 2783】【JLOI 2012】树【STL-set】
- bzoj2783 [JLOI2012]树
- bzoj 2783: [JLOI2012]树
- BZOJ2783: [JLOI2012]树
- bzoj2783 JLOI2012 树
- bzoj 2783: [JLOI2012]树 dfs+二分
- 【bzoj2783】【JLOI2012】树
- BZOJ 2783 JLOI 2012 树 乘+二分法
- 【BZOJ2783】【DFS】[JLOI2012]树 题解
- bzoj2783【JLOI2012】树
- 【JLOI2012】【BZOJ2783】树
- BZOJ 2783 [JLOI2012]树
- bzoj 2783 [JLOI2012] 树 题解
- [bzoj2783][JLOI2012]树_树的遍历
- BZOJ2783: [JLOI2012]树 dfs+set