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

}

相关推荐
江畔柳前堤11 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Doraemomo11 小时前
数据结构-环形链表
java·数据结构·链表
Forever Nore12 小时前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考14 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX14 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面15 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号15 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽16 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI16 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
MC皮蛋侠客17 小时前
Redis 系列(一):全景与最小闭环——从 `SET` 命令到内存数据结构
数据结构·数据库·redis