• 哈尔滨理工大学第七届程序设计竞赛决赛(网络赛-高年级组)H


    题目描述

    给一个有根二叉树,可以无限次的交换任意节点的左右子树,问最少交换多少次使得该树的中序遍历的字典序最小?

    输入描述:

    每个测试点有仅有一组数据
    每组测试数据的一行有两个整数N,M,代表有N个节点,M为根节点。
    接下来N行,每行两个整数ai,bi.ai表示第i个节点的左儿子,bi表示第i个节点的右儿子.

    N∈[1,5×105]
    ai,bi,M∈[1,N] 当ai,bi为0时 表示空节点.

    输出描述:

    输出两行
    第一行 为最小交换次数.
    第二行 为字典序最小的中序遍历.
    示例1

    输入

    7 4
    0 0
    1 3
    0 0
    2 5
    6 7
    0 0
    0 0

    输出

    0
    1 2 3 4 6 5 7

    题解

    树形$dp$。

    这题保证了每个数字都是不一样的,所以难度极小。记录$dp[i]$表示以$i$为根的子树中序遍历第一个数字的最小值,从下往上推一发就能知道哪些节点需要交换了。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int maxn = 5e5 + 10;
    int L[maxn], R[maxn];
    int f[maxn], p[maxn];
    int n, m;
    int u[maxn], sz;
    
    void dfs(int x) {
      if(L[x] == 0 && R[x] == 0) {
        p[x] = x;
        return;
      }
      if(L[x]) dfs(L[x]);
      if(R[x]) dfs(R[x]);
      if(L[x] != 0 && R[x] != 0) {
        if(p[L[x]] > p[R[x]]) {
          f[x] = 1;
          p[x] = p[R[x]];
        } else {
          p[x] = p[L[x]];
        }
      } else if(L[x] == 0) {
        if(p[R[x]] < x) {
          f[x] = 1;
          p[x] = p[R[x]];
        } else {
          p[x] = x;
        }
      } else {
        if(p[L[x]] > x) {
          f[x] = 1;
          p[x] = x;
        } else {
          p[x] = p[L[x]];
        }
      }
    }
    
    void work(int x) {
      if(L[x]) work(L[x]);
      u[sz ++] = x;
      if(R[x]) work(R[x]);
    }
    
    int main() {
      while(~scanf("%d%d", &n, &m)) {
        for(int i = 1; i <= n; i ++) {
          scanf("%d%d", &L[i], &R[i]);
          f[i] = 0;
          p[i] = 0;
        }
        dfs(m);
        int ans = 0;
        for(int i = 1; i <= n; i ++) {
          ans = ans + f[i];
          if(f[i]) swap(L[i], R[i]);
        }
        printf("%d
    ", ans);
        sz = 0;
        work(m);
        for(int i = 0; i < n; i ++) {
          printf("%d", u[i]);
          if(i < n - 1) printf(" ");
          else printf("
    ");
        }
      }
      return 0;
    }
    

      

  • 相关阅读:
    zepto的源代码注释(转)
    关于js的连续赋值
    一道js题
    深入理解setTimeout的作用域
    深入理解setTimeout和setinterval
    webapp之路--apple私有属性apple-touch-icon
    javascript中的原型继承
    webapp之路--百度手机前端经验(转)
    (转)浏览器的渲染原理
    node.js study: cluster
  • 原文地址:https://www.cnblogs.com/zufezzt/p/8065097.html
Copyright © 2020-2023  润新知