import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Queue;
import java.util.Deque;
import java.util.LinkedList;


public class Main {
    /**
     * 测试用例:( 注意官方给的输入数据有问题,更正后如下)
     * 8 1
     * 1 2 3
     * 2 4 0
     * 4 0 0
     * 3 5 6
     * 5 7 8
     * 7 0 0
     * 8 0 0
     * 6 0 0
     */
    public static void main(String[] args) throws Exception {
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        String[] firstRow = in.readLine().split(" ");
        int row = Integer.parseInt(firstRow[0]);
        TreeNode<String> root = TreeUtils.makeBinaryTreeByInput(in);

        //按层打印
        PrintByLevel.printByLevel2(root);

        System.out.println();

        //之字形打印
        PrintByZigZag.printByZigZag(root);

    }

}



/**
 * @描述:  按Z字形按层打印二叉树的节点
 * @思路:只使用一个双端队列dq
 * 定义规则:
 * 规则1:若顺序是从左到右,从dq的头部弹出节点node;若node有孩子,以“先左后右”的形式从尾部进入dq.
 * 规则2:若顺序是从右到左,从dq的尾部弹出节点node;若node有孩子,以“先右后左”的形式从头部进入dq.
 * 确定规则1和规则2转换时机:(实质是一个确定每一层最后一个节点的问题)
 * 经总结发现:**下一层最后打印的节点 == 当前层有孩子节点中最先进入dq的节点 **
 * @复杂度:
 * @链接:
 */
class PrintByZigZag {

    public static <T> void printByZigZag(TreeNode<T> root) {
        Deque<TreeNode<T>> queue =  new LinkedList<>();
        boolean isLeft = true;
        TreeNode last = root;
        TreeNode nlast = null;
        int level = 1;

        queue.add(root);
        pringLevelAndOrientation(level++, isLeft);

        while (!queue.isEmpty()) {
            TreeNode curr = null;
            if (isLeft) {
                curr = queue.pollFirst();
                if (curr.left != null) {
                    queue.addLast(curr.left);
                    nlast = nlast == null ? curr.left : nlast;
                }
                if (curr.right != null) {
                    queue.addLast(curr.right);
                    nlast = nlast == null ? curr.right : nlast;
                }
            } else {
                curr = queue.pollLast();
                if (curr.right != null) {
                    queue.addFirst(curr.right);
                    nlast = nlast == null ? curr.right : nlast;
                }
                if (curr.left != null) {
                    queue.addFirst(curr.left);
                    nlast = nlast == null ? curr.left : nlast;
                }
            }
            System.out.print(curr.value + " ");

            //换行时刻(注:其中!queue.isEmpty()判断只是为了打印好看,可忽略)
            if (curr == last && !queue.isEmpty()) {
                last = nlast;
                nlast = null;
                isLeft = !isLeft;

                System.out.println();
                pringLevelAndOrientation(level++, isLeft);
            }
        }
    }


    //只是为了打印好看
    public static void pringLevelAndOrientation(int level, boolean lr) {
        System.out.print("Level " + level + " from ");
        System.out.print(lr ? "left to right: " : "right to left: ");
    }


}



/**
 * @描述:按层遍历二叉树
 * @思路:进行宽度优先遍历,使用队列queue存储当前层和下一层的节点信息; 即: 从queue的头部弹出节点node;若node有孩子,以“先左后右”的形式从尾部进入queue.
 * @复杂度:时间O(N) 空间O(1)
 * @链接:https://www.nowcoder.com/practice/6a1815a85bfc411d9295bc017e6b6dbe
 */
class PrintByLevel {


    /*
     * 宽度优先遍历进阶版 - 按层换行打印
     * 如何确定换行?
     * 记录下"当前行的最右节点last" 和 "下一行的最右节点nlast"
     * 换行时刻:当前节点==last,然后更新last: last = nlast
     *
     * 结果形式:
     * Level 1:1
     * Level 2:2 3
     * Level 3:4 5
     */
    public static void printByLevel2(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        int level = 1;
        TreeNode last = root; //当前行的最右节点
        TreeNode nlast = null; //下一行的最右节点

        queue.offer(root);
        System.out.print("Level " + level++ + " : ");
        while (!queue.isEmpty()) {
            TreeNode curr = queue.poll(); // -- 核心点
            System.out.print(curr.value + " ");

            if (curr.left != null) {
                queue.offer(curr.left);
                nlast = curr.left;
            }
            if (curr.right != null) {
                queue.offer(curr.right);
                nlast = curr.right;
            }

            //换行时刻(注:其中!queue.isEmpty()判断只是为了打印好看,可忽略)
            if (curr == last && !queue.isEmpty()) {
                last = nlast;
                System.out.print("\nLevel " + level++ + " : ");
            }
        }
    }


    /*
     * 宽度优先遍历进阶版 - 按层换行打印
     * 如何确定换行?
     * 标识出 当前层和下一层的分界位置
     * 将队列中的值按层一次一次遍历;即:一次性将当前队列中的当前层的元素遍历完,再在一次性遍历下一层队列元素; 重点在于标识当前层和下一层的分界位置;
     */
    public static void printByLevel3(TreeNode root) {
        Queue<TreeNode> queue = new LinkedList<>();
        int level = 1;

        queue.offer(root);
        System.out.print("Level " + level++ + ":");
        while (!queue.isEmpty()) {
            int length = queue.size();  // - 核心点  区分:标识当前层和下一层的分界位置
            //换行时刻
            for (int i = 0; i < length; i++) {
                TreeNode curr = queue.poll();
                if (curr.left != null) {
                    queue.offer(curr.left);
                }
                if (curr.right != null) {
                    queue.offer(curr.right);
                }
                System.out.print(curr.value + " ");
            }

            //注:其中!queue.isEmpty()判断可忽略,这里只是为了打印好看,才加的判断
            if (!queue.isEmpty()) {
                System.out.print("\nLevel " + level++ + " : ");
            }

        }
    }



}



class TreeUtils {

    /**
     * 通过控制台输入的方式,采用递归的方式创建一颗二叉树
     */
    public static TreeNode<String> makeBinaryTreeByInput(BufferedReader in) throws Exception {
        String[] nodeVals = in.readLine().split(" ");
        //数组中第一个数是根节点
        TreeNode<String> node = new TreeNode<>(nodeVals[0]);
        //通过递归确定了层数
        if (!"0".equals(nodeVals[1])) {
            node.left = makeBinaryTreeByInput(in);
        }
        if (!"0".equals(nodeVals[2])) {
            node.right = makeBinaryTreeByInput(in);
        }
        return node;
    }

}



class TreeNode<T> {
    public T value;
    public TreeNode<T> left;
    public TreeNode<T> right;

    public TreeNode(T value) {
        this.value = value;
    }

    public TreeNode() {
    }

    public TreeNode(TreeNode left, T value, TreeNode right) {
        this.left = left;
        this.value = value;
        this.right = right;
    }


    public static int getHeight(TreeNode root) {
        if (root == null) {
            return 0;
        }
        int i = getHeight(root.left);
        int j = getHeight(root.right);
        return (i < j) ? j + 1 : i + 1;
    }


    public static int getSize(TreeNode root) {
        if (root == null) {
            return 0;
        }
        return 1 + getSize(root.left) + getSize(root.right);
    }

}