codeforces round# 302 (div1 D 树形计数)

本文介绍了一种基于树形结构的动态规划算法实现方法,通过递归计算每个节点的可行方案数,最终得出整棵树中所有节点的方案数。文章详细解释了如何利用父节点信息推导子节点的方案数,并提供了完整的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先这个题目要求的是对于给定的一刻树,求每个点到其他所有点每条路径上至多有一条不好的边,求问每个点的所有方案。

分析:

先求出1到所有点的可行性方案,那么其他点的值,可由该点递推出来。

考虑 fa[u] 代表u的父节点只不经过u的所有方案书, 那么ans[ u ] = d[ u ]*fa[u];(d[u] 代表以1为根的树只考虑从u往下走可行方案数)

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <list>
#include <cstdlib>
#include <queue>
#include <stack>
#include <cmath>
#include <bitset>
#include <cassert>
#define ALL(a) a.begin(), a.end()
#define clr(a, x) memset(a, x, sizeof a)
#define X first
#define Y second
#define pb push_back
#define lowbit(x) (x&(-x))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define rep1(i,x,y) for(int i=x;i<=y;i++)
#define rep(i,n) for(int i=0;i<(int)n;i++)
using namespace std;
const double eps = 1e-10;
typedef long long LL;
typedef long long ll;
typedef pair<int, int> pii;
const int oo =0x3f3f3f3f;

const int N = 2e5+1000;
const int mod = 1e9+7;
ll d[N];
vector<int> G[N];
ll dfs(int u){
   d[u] = 1;
   rep(i,G[u].size()) d[u] = d[u]*(dfs(G[u][i])+1)%mod;
   return d[u];
}
ll ans[N],l[N],r[N],up[N];
ll cal(int u){
   l[0] = 1; rep(i,G[u].size()) l[i+1]=l[i]*(d[G[u][i]]+1)%mod;
   r[G[u].size()-1] = 1; for(int i=G[u].size()-1;i>=1;i--) r[i-1] = r[i]*(d[G[u][i]]+1)%mod;
   rep(i,G[u].size()){
       int v = G[u][i];
       up[v] = (l[i]*r[i]%mod*up[u]+1)%mod;
       ans[v] = up[v]*d[v]%mod;
   }
   rep(i,G[u].size()) cal(G[u][i]);
}
int n;
int main()
{
   scanf("%d",&n);
   rep1(i,2,n){
      int x; scanf("%d",&x);
      G[x].push_back(i);
   }
   dfs(1);
   ans[1] = d[1]; up[1] = 1;
   cal(1);
   rep1(i,1,n){
       if(i>1) printf(" ");
       printf("%d",(int)ans[i]);
   } printf("\n");
   return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值