UVAL 3486 Cells DFS时间戳

题意:给出一颗树。有N个询问,每个询问有两个节点,判断前面的节点是否是后面节点的祖先。
思路:首先要注意到题目中最后树总节点的个数上限为20000000,而对时限是3s,所以算法的复杂度基本上确定为线性。
起初想的是用离线的Tarjan的LCA算法,直接求出两点的LCA,判断LCA是否和前面一个节点相等。然后RE了。最后仔细考虑,觉得应该是递归爆栈了,转换了写人工栈,时间变成了TLE,说明这个算法的复杂度还是比较高的。
首先我们要知道,这道题是没有让求出明确的公共祖先的点,所以我们求出了明确的点,相当于做了多余的东西。
正解是通过一遍DFS,得到每个节点的第一次访问的时间戳pre[u]和退出访问的时间戳post[u]。
在《算法导论》中,对于深度优先遍历树,有一个括号定理:对于u,v,两点,u是v的祖先,当且仅当,pre[u] < pre[v] 且post[u] > post[v](取不取等号要看题目中的定义)。
注意:1.这道题对祖先的定义而言,对于上面的括号定理,是不能加等号的,即自己不能是自己的祖先。
2.不能把图建立后,再用DFS求解,否则会超时。

代码如下:

#include <cstdio>
#include <algorithm>
#include &
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值