Description
https://loj.ac/problem/3023
一句话题意:给你一棵完全二叉树,每条边有一个方向,求这棵树有多少种不同的拓扑序。
Solution
简化题意后,其实就是一个普及组树形 DP。
设 (dp(i,j)) 表示以点 (i) 为根的子树中,(i) 号点排第 (j) 名的方案数。
利用 (j) 这个辅助维,我们可以枚举点 (i) 的排名 (k),扫一遍点 (i) 的所有儿子,每次会新来一个以 (v) 为根的子树合并到以 (i) 为根的子树上,枚举点 (i) 和点 (v) 在各自子树中的排名(记为 (rank_i) 和 (rank_v)),若题目限制点 (i) 排在点 (v) 前面,则枚举要满足 (rank_i+rank_vle k),否则题目限制点 (i) 排在点 (v) 后面,则枚举要满足 (rank_i+rank_vgt k)。
设从 ([1,k-1]) 中选 (rank_i-1) 个整数的方案数为 (L),从 ([k+1,size_i+size_v]) 中选 (size_i-rank_i) 个整数的方案数为 (R),则 (dp(i,k) += dp(i,rank_i) imes dp(v,rank_v) imes L imes R)。这很好理解。
最后算时间复杂度,还是那个套路,看起来是 (O(n^4)),其实还是 (O(n^3)),因为最里面两层循环的最大上界分别为 (size_i) 和 (size_v),这等价于在两棵子树内选 (2) 个点。那么这就是个以前讲过的套路,树上每对点只会在 LCA 处被枚举一次,故最里面两层循环套 dfs 的时间是 (O(n^2)),乘上一个枚举 (k) 的循环,总时间 (O(n^3))。