首页 > 代码库 > BZOJ 2783 JLOI2012 树 DFS

BZOJ 2783 JLOI2012 树 DFS

题目大意:给定一棵有根树,每个节点有权值,求有多少链上的权值和为S,要求链上节点的深度必须单调(即这条链由某个节点出发指向根)

DFS一遍,当深搜到一个点时将这个点加入队列,同时队头向后调整,使队列中元素之和<=s,记录ans

当一个点出栈时将队尾删除,同时队头向前调整,使队列中元素之和刚好<=s

这题1s略卡时间。。。不过我旁边的哥们用nlogn的算法超时700ms过去的0.0 这怎么过去的0.0 误差也太大了吧0.0

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 100100
using namespace std;
struct abcd{
	int to,next;
}table[M<<1];
int head[M],tot;
int n,s,ans,sum,a[M],fa[M],q[M],r,h;
void Add(int x,int y)
{
	table[++tot].to=y;
	table[tot].next=head[x];
	head[x]=tot;
}
void DFS(int x)
{
	int i;
	q[++r]=a[x];
	sum+=a[x];
	while(sum>s)
		sum-=q[++h];
	if(sum==s)
		++ans;
	for(i=head[x];i;i=table[i].next)
	{
		if(table[i].to==fa[x])
			continue;
		fa[table[i].to]=x;
		DFS(table[i].to);
	}
	sum-=q[r--];
	while(h&&sum+q[h]<=s)
		sum+=q[h--];
}
int main()
{
	int i,x,y;
	cin>>n>>s;
	for(i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for(i=1;i<n;i++)
		scanf("%d%d",&x,&y),Add(x,y),Add(y,x);
	DFS(1);
	cout<<ans<<endl;
}


BZOJ 2783 JLOI2012 树 DFS