题目
链接:https://ac.nowcoder.com/acm/problem/14506
给一个n(n<=1e5)个点,m点为根的有根二叉树,可以无限次的交换任意节点的左右子树,
问最少交换多少次使得该树的中序遍历的字典序最小
输出交换次数,输出交换后的中序遍历序列
题解
树形dp,维护子树出现的最小值即可,可利用回溯返回值来实现
分几种情况讨论,注意如果右子树的最小值比左子树的最小值小则交换,
其余没有一侧的子树的几种情况也差不多,最终把代码统一化简成如下最简形式
代码
#include <bits/stdc++.h>
using namespace std;
const int N=5e5+10;
int cost;
vector<int>dfn;
struct node
{
int l,r;
}e[N];
int dfs(int i)
{
int &l=e[i].l,&r=e[i].r,a=i,b=i;
if(l)a=dfs(l);
if(r)b=dfs(r);
if(a>b)swap(l,r),cost++;
return min(a,b);
}
void tra(int i)
{
int &l=e[i].l,&r=e[i].r;
if(l)tra(l);
dfn.push_back(i);
if(r)tra(r);
}
int main()
{
int n,rt,l,r;
scanf("%d%d",&n,&rt);
for(int i=1;i<=n;++i)
{
scanf("%d%d",&l,&r);
e[i].l=l;e[i].r=r;
}
dfs(rt);tra(rt);
printf("%d\n",cost);
for(int v:dfn)
printf("%d ",v);
return 0;
}