Codeforces 486D Valid Sets(dfs)

本文介绍了一种使用树形动态规划(DP)的方法来解决特定的节点选择问题。在一个给定的树结构中,每个节点都有一个权值,目标是选择一组节点,使得这些节点的权值最大值与最小值之差不超过预设值d,同时选择的节点组合数量达到最大。文章详细解释了如何通过枚举根节点并应用深度优先搜索(DFS)来避免重复计数,最终求得所有可能的选择方案。

题目大意:给定一棵树,每个节点有个权值,现在要选定一些节点,要求非空,并且maxVal-minVal不大于d。问说有多
少种选择方法。
解析:
枚举每个节点作为根节点
默认根节点为权值最大的节点
然后进行dfs
为了避免重复,在两个节点相等时,要求根节点大的时候才能继续进行
由于是乘法,所以longlong 很必要

#include<bits/stdc++.h>
using namespace  std;
#define ll long long
#define pb push_back
#define inf 2099999999
#define mod 1000000007
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define rep1(i,a,b) for(int i=a;i>=b;i--)
const int N=2e3+100;
ll arr[N];
vector<ll>G[N];
ll d;
/**

*/
ll dfs(int now ,int pre ,int rt)
{
    ll ret=1;
    for(int i=0;i<G[now].size();i++)
    {
        int y=G[now][i];
        if(y!=pre&&arr[rt]>=arr[y]&&arr[rt]-arr[y]<=d&&(arr[rt]!=arr[y]||rt>y))
            ret=(ret*(dfs(y,now,rt)+1))%mod;
    }
    return ret;
}
int main()
{
    #ifdef LOCAL_DEFINE
        freopen("D://rush.txt", "r", stdin);
    #endif
    ios::sync_with_stdio(false),cin.tie(0);
    ll n,a,b;
    cin>>d>>n;
    rep(i,1,n) cin>>arr[i];
    rep(i,1,n-1)
    {
        cin>>a>>b;
        G[a].pb(b);
        G[b].pb(a);
    }
    ll ans=0;
    rep(i,1,n)
    {
        ans=(ans+dfs(i,0,i))%mod;
    }
    cout<<ans<<endl;
    return 0;
}
请使用c++14 ## 题目描述 为了再现那日的彗星,Nana 和 Lily 需要使用特定的数对把一个序列变成另一个序列。 Nana 有一个长度为 $n$ 序列 $a$,Lily 每次可以选择一个下标 $i(1\le i<n)$,然后操作 $a_i\leftarrow x,a_{i+1}\leftarrow y$。 选定的 $1\le x,y\le k$ 需要满足 $f(a_i,a_{i+1})=f(x,y)=1$。Lily 最后需要把 $a$ 变成另一个长度为 $n$ 的序列 $b$。 其中,Nana 将给出一个 $k$ 个点 $m$ 条边的无向图 $G$,**不**保证没有重边和自环,则 $f(x,y)=1$ 当且仅当图上 $x$ 与 $y$ 之间存在连边。需要注意的是,如果有 $x$ 与 $x$ 之间的连边(一个自环)则 $f(x,x)=1$,否则 $f(x,x)=0$。 Lily 并不太关心构造的方案,所以她想让你多组测试询问 $a$ **是否**能变成另一个长度为 $n$ 的序列 $b$。 > “仍牢记我们之间的**约定**,在心中坚守着**秘密**。**若能化作彗星**,是否就能够**再会**呢。” ## 输入格式 每个数据点的开头有三个整数 $m,k,T$。 前 $m$ 行中,第 $i$ 行有两个整数 $x_i,y_i$ 表示第 $i$ 条边连接了 $(x_i,y_i)$。 接下来共 $T$ 组测试。 每组测试输入三行: 第一行一个整数 $n$。 第二行是一个长度为 $n$ 的序列 $a$,其中第 $i$ 个数是 $a_i$。 第三行是一个长度为 $n$ 的序列 $b$,其中第 $i$ 个数是 $b_i$。 ## 输出格式 对于一组测试,只需要输出一行一个字符串,如果能够成功把 $a$ 变成 $b$,输出 `YES`,否则输出 `NO`。 ## 输入输出样例 #1 ### 输入 #1 ``` 1 2 2 1 2 6 1 1 2 1 2 2 2 1 1 2 2 1 2 2 2 1 2 ``` ### 输出 #1 ``` YES NO ``` ## 说明/提示 ### 样例解释 对于第一组样例,我们有如下的操作方式: 1. 选择 $i=2$,序列变成 $[1,2,1,1,2,2]$。 2. 选择 $i=1$,序列变成 $[2,1,1,1,2,2]$。 3. 选择 $i=4$,序列变成 $[2,1,1,2,1,2]$。 4. 选择 $i=5$,序列变成 $[2,1,1,2,2,1]$。 对于第二组样例,显然你无法进行第一次操作。所以无法成功。 ### 数据范围 | Sub | 数据范围 | 特殊性质 |分数| | :---------: | :-----------: | :-----------: | :--: | | $1$ |$n\le 2$|图连通|$25$| | $2$ |$n\le 10^5$|图连通|$25$| | $3$ |$n\le 10^5$|图是森林|$25$| | $4$ |$n\le 10^5$|无|$25$| 本题开启子任务捆绑,你只有通过这个子任务中的所有测试点才能获得这个子任务对应的分数。 对于所有数据,$1\le T\le 10^4,2\le n\le 10^5,\sum n\le 10^6,1\le m\le 3\times 10^5,1\le k\le 2\times 10^5$。 保证 $1\le a_i,b_i,x_i,y_i\le k$。**不**保证图没有重边和自环。
最新发布
11-10
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值