Skip to content

M30680:森林局部排序遍历 ​

tree, http://cs101.openjudge.cn/practice/30680/

给定一个森林(由一棵或多棵树组成)。对于森林中的每一棵树,遍历规则如下:

  1. 局部排序规则:遍历到每个节点时,将该节点本身与其所有直接子节点的值放在一起,按从小到大的顺序进行遍历。
  2. 递归规则:
    • 如果遇到的是子节点,则递归进入该子节点进行深度遍历。
    • 如果遇到的是当前节点本身,则输出该节点的值。
  3. 森林规则:如果森林中存在多棵树,首先找到所有树的根节点,按照根节点的值从小到大的顺序依次对每棵树进行上述遍历。

每个节点的值为互不相同的正整数。

输入

第一行:节点总个数 n (n < 1000)。 接下来的 n 行:每行代表一个节点的结构。第一个数是此节点的值,之后的数表示它的所有直接子节点的值。如果没有子节点,该行只有一个数。

输出

输出遍历结果,每行一个节点的值。

样例输入

4
15 2
2
8 20
20

样例输出

8
20
2
15
# 解释:
1. 该输入构成了两棵树(一个森林):
   - 第一棵树:根为 15,子节点为 2。
   - 第二棵树:根为 8,子节点为 20。
2. 根节点集合为 {8, 15}。按规则,先处理较小的根 8。
3. 局部排序遍历根 8
4. 局部排序遍历根 15

来源

2026 spring yan

python
import sys

# 增加递归深度限制,防止深层树结构导致溢出
sys.setrecursionlimit(2000)

def solve():
    # 读取所有输入并按行处理
    input_data = sys.stdin.read().splitlines()
    if not input_data:
        return
    
    # 第一行是节点个数 n
    try:
        n = int(input_data[0].strip())
    except (ValueError, IndexError):
        return

    adj = {}
    all_nodes = set()
    all_children = set()
    
    # 处理接下来的 n 行输入
    line_count = 0
    for i in range(1, len(input_data)):
        if line_count >= n:
            break
        
        line = input_data[i].strip()
        if not line:
            continue
        
        parts = list(map(int, line.split()))
        parent = parts[0]
        children = parts[1:]
        
        adj[parent] = children
        all_nodes.add(parent)
        for child in children:
            all_children.add(child)
            
        line_count += 1
    
    # 根节点是所有节点中没有出现在子节点集合里的那个
    # 注意:即便某些叶子节点在输入中只有一行且没有子节点,它们也会被加入 all_nodes
    roots = list(all_nodes - all_children)
    
    # 如果没有找到根节点(理论上树结构必然有根),直接退出
    if not roots:
        return
    
    # 虽然题目暗示是一棵树,但如果是森林,我们按根节点大小排序后依次遍历
    roots.sort()

    def dfs(u):
        # 获取当前节点的子节点
        children_list = adj.get(u, [])
        
        # 核心规则:将父节点和所有子节点的值放在一起排序
        items = [u] + children_list
        items.sort()
        
        # 按照排序后的顺序进行遍历
        for item in items:
            if item == u:
                # 如果当前值是父节点,输出它
                print(item)
            else:
                # 如果当前值是子节点,递归进入该子节点
                dfs(item)

    # 从根节点开始执行
    for r in roots:
        dfs(r)

if __name__ == "__main__":
    solve()