Codeforces 486D Valid Sets

Posted icequarze

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}

以上是关于Codeforces 486D Valid Sets的主要内容,如果未能解决你的问题,请参考以下文章

[CF486D] Valid Sets - 树形dp

codeforces 486D

[Codeforces 1037D] Valid BFS?

XSY2410CF486D有效集合

[CF486D]有效集合-树形dp

codeforces666A