Codeforces1508D - Tree Calendar
Codeforces1508D - Tree Calendar
题目大意:
有一棵已知的有根树和一个未知的 \(\text{dfs}\) 序,且做了若干次操作,每次操作是
对于所有的 \((u,fa_u)\and label_{fa_u}<label_{u}\) ,找到最小的二元组 \((label_{fa_u},lable_u)\) ,交换二元组的 \(label\)
给定最终的序列,求复原一个 \(\text{dfs}\) 序并且给出操作次数,或者确定不存在这样的 \(\text{dfs}\) 序
\[ \ \]
模拟这样的过程,容易发现:
1号节点沿着最小 \(\text{dfs}\) 序路径走下去,直到叶子,同时将路径上的点推上来,一共推了 \(dep_{leaf}\) 次
2号节点沿着最小 \(\text{dfs}\) 序路径走下去,直到叶子,同时将路径上的点推上来,一共推了 \(dep_{leaf'}\) 次
....
考虑每个节点都已经推到最底下的情况,则最终所有的节点有两种情况
1.是推下来的节点,则其 \(label\) 恰好为原树上出栈序列的标号
2.剩下的点构成一个新的连通块,按照新的 \(\text{dfs}\) 序的顺序标号
那么考虑找到当前最小的二元组 \((label_{fa_u},label_u)\) ,就知道当前正在推的是哪个元素
考虑先复原这个元素被推下来的过程,复原的过程中注意判定是否当前的元组合法
然后容易通过当前的 \(label\) 确定一开始的 \(\text{dfs}\) 序
具体的,设 \(s_u\) 为 \(u\) 子树中最小的 \(label\) ,按照 \(s_u\) 递增的顺序遍历每个儿子得到的 \(\text{dfs}\) 才可能是合法的 \(\text{dfs}\) 序
原理比较显然,已经被推的叶子按照 \(\text{stack}\) 序遍历,剩下的按照原先的 \(\text{dfs}\) 序遍历,最终取 \(\text{min}\) 然后遍历即合法
然后按照上面的过程,对于得到的 \(\text{dfs}\) 序判定是否合法即可
1 |
|