[bzoj2783][JLOI2012]树_树的遍历

树 bzoj2783 JLOI2012

题目大意:给定一棵n个点的树。求满足条件的路径条数。说一个路径是满足条件的,当且仅当这条路径上每个节点深度依次递增且点权和为S。

注释:$1\le n\le 10^5$,$1\le S,val_i\le 10^3$。



想法:翻lijinnn的blog翻到的水题。

我们直接遍历整棵树,遍历的时候维护全局桶。然后在回溯的时候将这个点对应的dis删除。这样遍历到每个点时桶内对应的就是这个点到根节点的dis桶,直接统计答案即可。

最后,附上丑陋的代码... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#define N 100010
using namespace std;
multiset<int>s;
bool v[N];
int to[N],nxt[N],head[N];
int w[N];
int tot,sum;
int root;
int ans=0;
inline char nc()
{
	static char *p1,*p2,buf[100000];
	return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int read()
{
	int x=0; char c=nc();
	while(!isdigit(c)) c=nc();
	while(isdigit(c)) x=(x<<3)+(x<<1)+c-‘0‘,c=nc();
	return x;
}
inline void add(int x,int y)
{
	to[++tot]=y;
	nxt[tot]=head[x];
	head[x]=tot;
}
void dfs(int x,int pre,int data)
{
	s.insert(data);
	int tmp=data+w[x];
	ans+=s.count(tmp-sum);
	for(int i=head[x];i;i=nxt[i])
		dfs(to[i],x,tmp);
	s.erase(data);
}
int main()
{
	int n=read(); sum=read();
	for(int i=1;i<=n;i++) w[i]=read();
	for(int x,y,i=1;i<n;i++)
	{
		x=read(),y=read();
		add(x,y); v[y]=1;
	}
	for(int i=1;i<=n;i++) if(!v[i]) root=i;
	dfs(root,0,0);
	printf("%d",ans);
	return 0;
}

小结:裙子的简单数据结构的例题。

原文地址:https://www.cnblogs.com/ShuraK/p/9537232.html

时间: 2024-10-13 16:38:37

[bzoj2783][JLOI2012]树_树的遍历的相关文章

.Net常用技巧_树控件工具类

using System; using System.Collections.Generic; using System.Text; using System.Collections; using DevComponents.AdvTree; namespace MyUtility { /// <summary> /// 树控件工具类 /// </summary> public class TreeTool { ArrayList selectArray = new ArrayLi

算法学习 - 表达树的建立(后缀表达式法),树的先序遍历,中序遍历,后序遍历

表达树就是根据后缀表达式来建立一个二叉树. 这个二叉树的每个叶子节点就是数,真祖先都是操作符. 通过栈来建立的,所以这里也会有很多栈的操作. 树的先序遍历,中序遍历,后序遍历的概念我就不讲了,不会的自行百度,不然也看不懂我的代码. 下面是代码: // // main.cpp // expressionTree // // Created by Alps on 14-7-29. // Copyright (c) 2014年 chen. All rights reserved. // #includ

【编程题目】判断整数序列是不是二元查找树的后序遍历结果,如果是,构建该二元查找树

判断整数序列是不是二元查找树的后序遍历结果题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果.如果是返回 true,否则返回 false.例如输入 5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果:8/ \6 10/ \ / \5 7 9 11因此返回 true.如果输入 7.4.6.5,没有哪棵树的后序遍历的结果是这个序列,因此返回 false. 做这个题目的时候最开始傻了,想着从前到后根据数字的大小关系判断.后来幡然醒悟,根据后序遍历的特点.序列最后一

树的先序遍历的栈实现

树的先序遍历的栈实现 先把根节点访问了,右子树入栈,去访问左子树. 1 void preorder(tree bt) //先序遍历bt所指的二叉树 2 { 3 tree stack[n]; //栈 4 int top = 0; //栈顶指针 5 tree P; 6 while(bt || top) 7 { 8 while(bt) //非叶结点 9 { 10 cout << bt->data; //访问根 11 stack[++top] = bt->rchild; //右子树压栈 1

数据结构第三部分:树与树的表示、二叉树及其遍历、二叉搜索树、平衡二叉树、堆、哈夫曼树、集合及其运算

参考:浙大数据结构(陈越.何钦铭)课件 1.树与树的表示 什么是树? 客观世界中许多事物存在层次关系 人类社会家谱 社会组织结构 图书信息管理 分层次组织在管理上具有更高的效率! 数据管理的基本操作之一:查找(根据某个给定关键字K,从集合R 中找出关键字与K 相同的记录).一个自然的问题就是,如何实现有效率的查找? 静态查找:集合中记录是固定的,没有插入和删除操作,只有查找 动态查找:集合中记录是动态变化的,除查找,还可能发生插入和删除 静态查找——方法一:顺序查找(时间复杂度O(n)) int

微软算法100题09 判断整数序列是不是二元查找树的后序遍历结果

9. 判断整数序列是不是二元查找树的后序遍历结果题目:输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果.如果是返回true,否则返回false.例如输入5.7.6.9.11.10.8,由于这一整数序列是如下树的后序遍历结果:8/ \6 10/ \ / \5 7 9 11因此返回true.如果输入7.4.6.5,没有哪棵树的后序遍历的结果是这个序列,因此返回false. 思路:如果一个数组为BST的后序遍历结果 则最后一个元素必然为该BST的根节点 因为BST的特性是左子树必然全部小

树的几种遍历

树的几种遍历,码迷,mamicode.com

树与森林的遍历

一.树的遍历 1.先根(次序)遍历树 先访问树的根节点,然后依次先根遍历根的每棵子树 2.后根(次序)遍历 先依次后根遍历每棵子树,然后访问根结点. 上面的先根遍历为:A B C D E 上面的后根遍历为:B D C E A 二.森林的遍历 1.先序遍历森林 若森林非空,则可按照下述规则遍历之: (1)访问森林中第一棵树的根节点 (2)先序遍历第一棵树中根结点的子树森林 (3)先序遍历出去第一棵树之后剩余的树构成的森林. 2.中序遍历森林 若森林非空,则可按照下述规则遍历: (1)中序遍历森林中

IT公司100题-9-判断整数序列是不是二元查找树的后序遍历结果

问题描述: 输入一个整数数组,判断该数组是不是某二元查找树的后序遍历的结果. 如果是返回true,否则返回false. 例如输入4, 8, 6, 12, 16, 14, 10,由于这一整数序列是如下树的后序遍历结果: 10/     \6      14/  \    /   \4   8 12    16 因此返回true. 如果输入6, 5, 8, 5, 7 ,则返回false. 分析: 在后续遍历得到的序列中,最后一个元素为树的根结点.根节点元素将数组分为两部分,左边都小于根节点,右边都大