https://loj.ac/problem/2324

太智障,一开始以为中序遍历的第一个点一定是一个叶子,想了个贪心。然而,手算了一下,第一个点都过不了啊。

input

5
2 3 4
1 3
3 5 1 2
1 1
1 3

output

1 2 3 5 4

如果树的形态确定,那么第一个中序遍历应该是,从根开始一直往左儿子走,直到当前点没有左儿子,那么这个点就是第一个走到的点。

这个点的度一定$<3$。

于是把贪心稍微换了换,一不小心就A了。

我们找到度$<3$的编号最小的点$d$作为中序遍历走到的第一个点。

然后他的度是1或者2。我们知道,根的度也是1或者2。

如果是2,我要选一条作为父边,一个作为右儿子的儿边。

比较哪个作为右儿子更优。如果一个点作为右儿子,那么他这个子树里面,度数$<3$的编号最小的点,编号一定尽量小。

因为那个点会是我们下一个会走到的点。

然后对于已经确定了是右儿子的那个树,我们可以dfs贪心求字典序最小的中序遍历。

那么,我们想一下,我现在确定了父边,我就可以继续往父边走,

如果这个点的度数$=3$,其中一度是左儿子我们走来的地方,剩下两天边,我们用相同方式比较,看哪个作为右儿子更优。

如果当前这个点度数$=1$,我们找到了根。

如果当前这个点度数$=2$,如果当前这个点可以是根也可以不是根。

我们要判断一下他作为根(那条边作为右儿子)更优还是,那条边作为父边更优。

具体比较方式是,我们看这个条边所到达点$x$,是$x$要小一些还是$x$子树里面度数$<3$的编号最小的点的编号小一些。

如果找到了根,那么就对于右子树dfs贪心求字典序最小的中序遍历。

我们做这道题的时候,就用$d$为根建树,然后预处理每个子树度数$<3$的编号最小的点。

我的代码中,dfs1表示还没有找到根,即,我在$d$到根的路径上。dfs2表示确定了一棵子树,我贪心求中序遍历。

//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
#define ll long long
#define db double
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rep(i,a,b) for(int i=(a);i>=(b);--i)
const int maxn=2e6+7,INF=0x3f3f3f3f;
int n,d[maxn],s[maxn],RT; char cc;ll ff;
template<typename T>void read(T& aa) {
aa=0;cc=getchar();ff=1;
while((cc<'0'||cc>'9')&&cc!='-') cc=getchar();
if(cc=='-') ff=-1,cc=getchar();
while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
aa*=ff;
} int fir[maxn],nxt[maxn],to[maxn],e=0;
void add(int x,int y) {
to[++e]=y;nxt[e]=fir[x];fir[x]=e;
} void DFS(int pos,int f) {
if(d[pos]==3) s[pos]=INF; else s[pos]=pos;
int y,z;
for(y=fir[pos];y;y=nxt[y]) {
if((z=to[y])==f) continue;
DFS(z,pos);
s[pos]=min(s[pos],s[z]);
}
}
#define lc son[0]
#define rc son[1]
int ans[maxn],tot; void dfs2(int pos,int f) {
int son[2],p=0,y,z;
for(y=fir[pos];y;y=nxt[y]) {
if((z=to[y])==f) continue;
son[p++]=z;
}
if(p==0) {ans[++tot]=pos;return;}
if(p==1) {
if(s[lc]<pos) dfs2(lc,pos),ans[++tot]=pos;
else ans[++tot]=pos,dfs2(lc,pos);
return;
}
if(s[lc]<s[rc]) dfs2(lc,pos); else dfs2(rc,pos);
ans[++tot]=pos;
if(s[lc]>s[rc]) dfs2(lc,pos); else dfs2(rc,pos);
} void dfs1(int pos,int f) {
int son[2],p=0,y,z; ans[++tot]=pos;
for(y=fir[pos];y;y=nxt[y]) {
if((z=to[y])==f) continue;
son[p++]=z;
}
if(p==0) return;
if(p==1) {//root or not root
if(lc>s[lc]) dfs2(lc,pos);
else dfs1(lc,pos);
return;
}
if(s[lc]<s[rc]) dfs2(lc,pos),dfs1(rc,pos);
else dfs2(rc,pos),dfs1(lc,pos);
} int main() {
read(n); int x;
For(i,1,n) {
read(d[i]);
if(d[i]<3&&RT==0) RT=i;
For(j,1,d[i]) {
read(x);
add(i,x);
}
}
DFS(RT,0);
dfs1(RT,0);
For(i,1,n) printf("%d ",ans[i]);
printf("\n");
return 0;
}

loj2324 「清华集训 2017」小 Y 和二叉树的更多相关文章

  1. LOJ2324「清华集训 2017」小Y和二叉树

    题目链接 瞎jb贪一发就过了.首先度数<=2且编号最小的点一定是中序遍历最靠前的点,我们从这个点开始dfs一遍算出子树中度数<=2且编号最小的点记为\(f(i)\),然后从这个点开始一步一 ...

  2. LOJ2324. 「清华集训 2017」小 Y 和二叉树【贪心】【DP】【思维】【好】

    LINK 思路 首先贪新的思路是处理出以一个节点为根所有儿子的子树中中序遍历起始节点最小是多少 然后这个可以两次dfs来DP处理 然后就试图确定中序遍历的第一个节点 一定是siz<=2的编号最小 ...

  3. Loj #2324. 「清华集训 2017」小 Y 和二叉树

    Loj #2324. 「清华集训 2017」小 Y 和二叉树 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙上, ...

  4. [LOJ#2324]「清华集训 2017」小Y和二叉树

    [LOJ#2324]「清华集训 2017」小Y和二叉树 试题描述 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙 ...

  5. loj #2325. 「清华集训 2017」小Y和恐怖的奴隶主

    #2325. 「清华集训 2017」小Y和恐怖的奴隶主 内存限制:256 MiB时间限制:2000 ms标准输入输出 题目类型:传统评测方式:文本比较   题目描述 "A fight? Co ...

  6. [LOJ#2323]「清华集训 2017」小Y和地铁

    [LOJ#2323]「清华集训 2017」小Y和地铁 试题描述 小Y是一个爱好旅行的OIer.一天,她来到了一个新的城市.由于不熟悉那里的交通系统,她选择了坐地铁. 她发现每条地铁线路可以看成平面上的 ...

  7. 【loj2325】「清华集训 2017」小Y和恐怖的奴隶主 概率dp+倍增+矩阵乘法

    题目描述 你有一个m点生命值的奴隶主,奴隶主受伤未死且当前随从数目不超过k则再召唤一个m点生命值的奴隶主. T次询问,每次询问如果如果对面下出一个n点攻击力的克苏恩,你的英雄期望会受到到多少伤害. 输 ...

  8. LibreOJ #2325. 「清华集训 2017」小Y和恐怖的奴隶主(矩阵快速幂优化DP)

    哇这题剧毒,卡了好久常数才过T_T 设$f(i,s)$为到第$i$轮攻击,怪物状态为$s$时对boss的期望伤害,$sum$为状态$s$所表示的怪物个数,得到朴素的DP方程$f(i,s)=\sum \ ...

  9. LOJ2325. 「清华集训 2017」小 Y 和恐怖的奴隶主【矩阵快速幂优化DP】【倍增优化】

    LINK 思路 首先是考虑怎么设计dp的状态 发现奴隶主的顺序没有影响,只有生命和个数有影响,所以就可以把每个生命值的奴隶主有多少压缩成状态就可以了 然后发现无论是什么时候一个状态到另一个状态的转移都 ...

随机推荐

  1. 【主席树】 [CQOI2015]任务查询系统

    模板题... 差分,然后用主席树维护时间点上的优先值和就好了 就是细节烦... #include<bits/stdc++.h> #define int long long #define ...

  2. Python全栈开发:基本数据类型

    1.数字 int(整型) 在32位机器上,整数的位数为32位,取值范围为-2**31-2**31-1,即-2147483648-2147483647 在64位系统上,整数的位数为64位,取值范围为-2 ...

  3. 【默默努力】vue-pc-app

    最近在github上面看到了一个团队的项目,真的非常赞.他们进行vue-cli的二次开发,将项目用自己的方式打包. 今天的这个开源项目地址为:https://github.com/tffe-team/ ...

  4. [转]C# 之泛型详解

    什么是泛型 我们在编写程序时,经常遇到两个模块的功能非常相似,只是一个是处理int数据,另一个是处理string数据,或者其他自定义的数据类型,但我们没有办法,只能分别写多个方法处理每个数据类型,因为 ...

  5. Loadrunner学习---脚本编写(1)

    Loadrunner学习---脚本编写(1) 中午看了两集<奋斗>发现越看越想看,但是想到好不容易没上班,在家还是赶紧学习下LR的知识吧.下面这个网页的文章原来也是看过的,但发现没几天就忘 ...

  6. day08 网络设置、软件包管理

    网络设置 ifconfig //最小化安装时不可用,需要安装安装包,命令为查看网卡信息 yum install net-tools mtu 网卡的最大发送字节 iptables -F 清掉防火墙配置 ...

  7. bootStrap-treeview插件

    简要教程 bootstrap-treeview是一款效果非常酷的基于bootstrap的jQuery多级列表树插件.该jQuery插件基于Twitter Bootstrap,以简单和优雅的方式来显示一 ...

  8. PAT甲级——A1089 Insert or Merge

    According to Wikipedia: Insertion sort iterates, consuming one input element each repetition, and gr ...

  9. linux操作mysql命令快速手记 — 让手指跟上思考的速度(二)

    这一篇是<mysql内建命令快速手记>的姐妹篇,废话不再赘述,直接上干货,跟老铁慢慢品 1.mysql -hlocalhost -uroot -proot,-h,-u,-p分别代表ip,u ...

  10. 抓包:MySQL Sniffer

    1.依赖文件安装 依赖glib2-devel.libpcap-devel.libnet-devel [root@VMUest ~]# yum install cmake [root@VMUest ~] ...