CF-EDU-175 D. Tree Jumps

D. Tree Jumps


原题链接

题意简述

给定一颗根为 \(1\) 的树,求合法路径的数量,合法路径定义为下,从根节点出发,如果当前节点是根节点,移动到任意连边。如果不是根节点,移动到当前节点深度+1且与当前节点不相连的边。

解题思路

树上问题考虑树上动态规划,定义 \(dp_i是第i个节点为终点的合法路径数量\),那么有
\(dp_i=\sum_{j,d_j=d_i-1} dp_j-dp_{fa_i}\) ,即每个点的合法路径是由上一层所有不是当前点爸爸的点的和决定的,考虑拿 \(sum\) 变量维护一个新的数组记录每一层合法路径数量和,然后由于\(\sum_{j,d_j=d_i-1} dp_j-dp_{fa_i}=sum_{d{i-1}}-dp_{fa_i}\)的性质 就可以在\(O(1)\)时间的完成查询。由于需要按层规划状态,所以使用队列维护bfs逐层转移累加 \(dp_i\) 即可.

AC code

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
constexpr ll N=3e5+5;
constexpr ll mod=998244353;
vector<int>G[N];
ll sum[N],f[N];
int d[N];
void solve(){
    int n;cin>>n;
    vector<int>fa(n+2);
    queue<int>Q;
    ll ans=1;
    sum[1]=d[1]=1;
    for(int i=2;i<=n;i++) cin>>fa[i],G[fa[i]].push_back(i);
    Q.push(1);
    while(!Q.empty()){
        int u=Q.front();
        Q.pop();
        d[u]=d[fa[u]]+1;
        f[u]=(sum[d[u]-1]-f[fa[u]]+mod)%mod;
        sum[d[u]]=(sum[d[u]]+f[u])%mod;
        ans=(ans+f[u])%mod;
        for(auto &v:G[u]) Q.push(v);
    }
    cout<<ans<<endl;
    fill(G+1,G+1+n,vector<int>());
    fill(sum+1,sum+1+n,0LL);
    fill(f+1,f+1+n,0LL);
}
int main(){
    cin.tie(0)->ios::sync_with_stdio(false);
    int T;cin>>T;
    while(T--) solve();
    return 0;
}
posted @ 2025-05-28 17:08  usedchang  阅读(15)  评论(0)    收藏  举报