您的位置:首页 > 其它

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通道
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: