给出了树。边缘信息以邻接列表格式给出。
节点编号分别为1,2,3 ...... N。
树的根总是1。
现在,给出了两个指数。问题是上述两个索引的关键在于从根(1)到其他索引的方式。
约束
示例: -
边缘: -
1 2
2 5
1 3
3 7
1 4
4 8
8 9
问题 -
2 3 ( Answer - Not possible, from 1 to 2, 3 never comes in between and from 1 to 3, 2 never comes in between.)
8 9 ( Answer - Possible, 8 lies in between 1 and 9)
下一个例子: -
1 2
2 4
2 5
1 3
3 6
3 7
3 8
答案 0 :(得分:1)
假设父节点的ID(靠近根节点的ID)总是大于子节点的ID,就像你的例子中的情况一样,你可以从任何边缘轻松看到它是否引向根或远离它。因此基本算法将是:
given nodes n and m
find edge (x, n) or (n, x) such that x < n
repeat with node x until x is m or x is root
我不认为有更快的方法来确定一个节点是否在&#39;之间?根和另一个。当然,您可以通过使用适当的数据结构来提高性能,例如首先将每个节点映射到哈希集中的父节点。这是Python中的一个例子:
ROOT = 1
edges = ((1, 2), (2, 4), (2, 5), (1, 3), (3, 6), (3, 7), (3, 8))
parents = {}
for edge in edges:
parent, child = min(edge), max(edge)
parents[child] = parent
def is_anchestor_of(p, c):
while c > p:
if parents[c] == p:
return True
c = parents[c]
return False
创建哈希映射的时间和空间复杂度在节点或边的数量上是O(n)(在树中几乎相同),is_anchestor_of
的平均大小写复杂度是O(logn),但在最坏的情况下(非常不平衡的树或链)会恶化为O(n)。
您可以通过将每个节点映射到其所有的安慰者来提高查找复杂性。创建这个哈希映射的复杂性将是O(n log n),除非我误解了时间和空间,但在最坏的情况下可能会达到O(n ^ 2)。在任何情况下,使用这种结构,is_anchestor_of
的复杂性是O(1),因为它只是在哈希映射中查找,然后在哈希集中查找。
anchestors = {}
for node in parents:
anchestors[node] = set([ ROOT ])
p = parents[node]
while p != ROOT:
anchestors[node].add(p)
p = parents[p]
def is_anchestor_of(p, c):
return p in anchestors[c]
在这两种情况下,只需检查一个人是否是另一个的安慰者。
def on_one_path(x, y):
return is_anchestor_of(x, y) if x < y else is_anchestor_of(y, x)
print on_one_path(3, 8)
更新:似乎有一种更有效的方法;请参阅 @ Loha的答案。
答案 1 :(得分:1)
算法如下: -
一个节点&#34; B&#34;是其他节点的后代&#34; A&#34;,只在一种情况下。
IN_TIME(A)&lt; IN_TIME(B)和OUT_TIME(B)&lt; Out_time的(A)强>
这样,Query将处理 O(1)时间。
答案 2 :(得分:0)
对于每个节点,在树中构建其上方节点的排序列表:
1 {}
2 {1}
3 {1}
4 {1}
5 {1, 2}
7 {1, 3}
8 {1, 4}
9 {1, 4, 8}
然后,当给出查询时,搜索列表中属于另一个的每个节点( O(logN)):
2 3: 2 is not in {1}, and 3 is not in {1}, so the answer is no.
8 9: 9 is not in {1, 4}, but 8 is in {1, 4, 8}, so the answer is yes.
修改
正如tobias_k所指出的,还有其他结构,例如哈希表,可以使搜索 O(1)。构建表格是 O(n),非常简单 - 只需迭代边缘列表并将它们放入。