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

树 bzoj2783 JLOI2012

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

注释:$1le nle 10^5$,$1le S,val_ile 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