Codeforces 486D Valid Sets

题意:

 给定一棵树,任意选定两个节点(也可以是同一个节点),使这两个点和连接这两个点的路径上的点中最大值和最小值小于d

题解:

 依次选定每一个节点并假设它是根节点(这棵树不一定是二叉树),同时假定根节点的值最大。从根节点开始遍历子节点,每一个子节点要满足以下性质:

  • 子节点的值要小于等于根节点的值
  • 子节点的值与根节点的值之差小于等于d
  • 特别的,如果某一个子节点的值等于根节点,那么使这个子节点为根节点时就会发生重复。为了去除这一情况,从根节点向下遍历时,我们要求与根节点值相同的点的原序号要大于根节点的原序号

dfs函数的实现:

long long int sum;	//包括当前节点的子树的数量

 对于一个节点如果它自身不符合要求,返回0,否则sum=1(自己算一个)。遍历每一个子节点:如果子节点dfs返回0无子树,只有一种可能性--不选这个子节点,sum=1;如果子节点dfs返回大于零,两种可能性:选或不选,sum=(dfs(子节点)+1)

题解代码

#include <iostream>
#include <vector>
#include <cmath>
#define MOD ((ll)1e9+7)
using namespace std;
typedef long long int ll;
ll a[2010];
ll d,n;
vector<ll> node[2010];
ll dfs(ll pos,ll root,ll parent){		//dfs(Current node, Root node, Parent node)
	if(a[pos]>a[root] || a[root]-a[pos]>d || 
		(a[pos]==a[root]&&pos<root)){
		return 0;
	}
	ll sum=1;
	for(ll& i:node[pos]){
		if(i!=parent){
			sum*=(dfs(i,root,pos)+1);
			sum%=MOD;
		}
	}
	return sum;
}
int main(){
	cin>>d>>n;
	for(int i=1;i<=n;++i){
		cin>>a[i];
	}
	for(int i=1;i<=n-1;++i){
		int u,v;
		cin>>u>>v;
		node[u].push_back(v);
		node[v].push_back(u);
	}
	ll sum=0;
	for(int i=1;i<=n;++i){
		ll t=dfs(i,i,0);
		sum+=t;
		sum%=MOD;
	}
	cout<<sum<<endl;
	return 0;
}
posted @ 2018-02-28 23:03  IceQuarze  阅读(185)  评论(0编辑  收藏  举报