树上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;

}

相关推荐
地平线开发者2 小时前
【模型轻量化专题】衡量模型轻量性的指标
算法
学习星球5 小时前
OFDM技术精讲:正交性推导、循环前缀原理与80行Python链路仿真(附实测数据)
算法·面试·前端框架
alphaTao11 小时前
LeetCode 每日一题 2026/8/24-2026/8/30
python·算法·leetcode
Interview Aid11211 小时前
TikTok OA 四题分享|半小时内 AC,题目基本都是实现题
java·开发语言·算法·面试·职场和发展
顶点多余20 小时前
那些在算法中适合巩固的知识点---1
java·前端·算法
AI情绪识别开源21 小时前
检信 ALLEMOTION OS 加密打包可执行程序 — 全面测试报告版本: v1.3功能测试 / 性能测试 /
开发语言·数据结构·人工智能·功能测试
罗西的思考1 天前
【Agentic RL / 强化学习框架】Molt 设计解读
人工智能·算法·机器学习
hahaha60161 天前
HLS高层次综合设计技巧--C++类和模板
图像处理·人工智能·算法·计算机视觉
多弗朗皮卡丘1 天前
算法详解4:买卖股票的最佳时机系列(上)
算法
维克兜率天1 天前
【维克】动量指标家族:RSI、ROC、CCI、Momentum全面解析
python·算法