树上dp问题

给定一棵n个节点的有根树,节点编号范围为1∼n,其中根节点编号为1。现在你需要给树上每个节点赋值左括号(或者右括号),问你有多少种赋值方案,使得赋值完毕后从根节点到达每一个叶子节点的唯一简单路径所经过的点构成的括号串是一个合法括号串(求出方案数对998244353取模的结果)?

我们递归的定义合法括号串:

  • 空括号串是合法的。
  • A合法,则(A)合法。
  • AB合法,则AB合法。
格式

输入格式:

第一行一个整数T(1≤T≤500),表示测试数据组数,对于每组测试数据:

第一行一个整数n(1≤n≤3000)。

接下来n−1n−1行,每行两个整数u,v(1≤u,v≤n),表示点uu与点vv之间有一条边。

保证单个测试点的所有组测试数据的nn之和不超过3000。

输出格式:

对于每组测试数据:

输出一行一个整数,表示答案。

样例 1

输入:

复制代码
1
4
1 2
2 3
3 4

复制

输出:

复制代码
2

复制

样例 2

输入:

复制代码
1
11
1 2
1 3
1 4
2 5
2 8
3 10
5 6
5 7
8 9
10 11

复制

输出:

复制代码
4

复制

备注

对于样例11,这是一条链,合法的括号串有()()(())两种,答案为2。

#include <iostream>

#include <vector>

using namespace std;

const int MOD = 998244353;

vector<int> adj3005;

long long dp30053005;//来到u节点前,欠j个左括号,到根后能形成的合法方案数

int n;

void dfs(int u, int p) {

// 1. 先递归处理子节点

vector<int> children;

for (int v : adju) {

if (v != p) {

children.push_back(v);

dfs(v, u);

}

}

// 2. 计算当前节点在不同初始余额 j 下的方案数

// j 是"进入节点 u 之前"的余额

for (int j = 0; j <= n; ++j) {

long long ways_as_L = 0;

long long ways_as_R = 0;

// 情况 A: 节点 u 填左括号 '('

// 填完后余额变为 j + 1

if (j + 1 <= n) {

if (children.empty()) {

// 如果 u 是叶子,填 '(' 后余额为 j+1

// 路径结束要求余额必须为 0,所以 j+1 == 0 (不可能)

ways_as_L = 0;

} else {

ways_as_L = 1;

for (int v : children) {

ways_as_L = (ways_as_L * dpvj + 1) % MOD;

}

}

}

// 情况 B: 节点 u 填右括号 ')'

// 填完后余额变为 j - 1

if (j - 1 >= 0) {

if (children.empty()) {

// 如果 u 是叶子,填 ')' 后余额为 j-1

// 路径结束要求余额必须为 0,即 j 必须是 1

ways_as_R = (j - 1 == 0 ? 1 : 0);

} else {

ways_as_R = 1;

for (int v : children) {

ways_as_R = (ways_as_R * dpvj - 1) % MOD;

}

}

}

dpuj = (ways_as_L + ways_as_R) % MOD;

}

}

void solve() {

cin >> n;

for (int i = 1; i <= n; i++) {

adji.clear();

for (int j = 0; j <= n; j++) dpij = 0;

}

for (int i = 0; i < n - 1; i++) {

int u, v;

cin >> u >> v;

adju.push_back(v);

adjv.push_back(u);

}

// 题目要求根节点到叶子的路径。根节点编号为 1。

dfs(1, 0);

// 最终答案是:进入根节点 1 之前,余额为 0 的方案数

cout << dp10 << endl;

}

int main() {

ios::sync_with_stdio(false);

cin.tie(0);

int T;

cin >> T;

while (T--) {

solve();

}

return 0;

}

相关推荐
罗西的思考19 小时前
机器人 / 强化学习】HIL-SERL:人类在环驱动的具身智能进化框架
人工智能·算法·机器学习
CSharp精选营1 天前
关系型 vs 非关系型:从原理到选型,一文搞定数据库核心分类
数据结构·nosql·关系型数据库·非关系型数据库·技术选型
美团技术团队1 天前
LongCat 开源 VitaBench 2.0:长期动态智能体基准新标杆
人工智能·算法
To_OC2 天前
LC 207 课程表:刚学图论那会儿,我连这是拓扑排序都没看出来
javascript·算法·leetcode
To_OC2 天前
LC 208 实现 Trie 前缀树:曾被名字劝退,写完发现是送分题
javascript·算法·leetcode
BadBadBad__AK2 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
_清歌2 天前
DSpark 深度解读:DeepSeek-V4 如何用「半自回归」把推理速度提升 85%
算法
统计实现局2 天前
SVD 的三步走:双对角化、Givens 收敛、排序
算法
躬行见万象2 天前
《VLA 系列》UniLab 强化训练 | G1 机器人 |复现
算法