📜  门| GATE CS Mock 2018 |设置 2 |第 63 题(1)

📅  最后修改于: 2023-12-03 15:28:39.426000             🧑  作者: Mango

门 | GATE CS Mock 2018 |设置 2 |第 63 题

在GATE CS模拟测试2018中,第63题涉及到门的题目,以下为详细介绍。

题目描述

在一个电路图中,有n个门,每个门都有两个输入和一个输出。两个输入可以是0或1。输出等于两个输入中的一个,由一个称为S的开关决定。如果S为0,则输出为第一个输入;否则,输出为第二个输入。在一个门与另一个门之间,可以使用其他的元件来进行连接。

现在,给定一棵无向树,每个节点都有一个门,树根为门的输入之一。现在需要你从根节点开始执行一些查询操作。对于每个查询,在树上依次遍历,对于经过的每个节点,使用该节点的门将输入转换为输出。你需要输出最终路径的异或和。

输入:

  • 第一行包含一个整数n (1≤n≤100,000),表示门的数量。
  • 第二行包含一个表示树根的整数r (1≤r≤n)。
  • 接下来n行,每行描述一个门。第i行包含三个整数xi,yi和si (1≤xi,yi≤n,0≤si≤1),表示门的两个输入xi和yi,以及开关si。
  • 接下来包含一个整数q (1≤q≤10,000),表示查询次数。
  • 接下来q行,每行包含两个整数ui和vi,表示查询从节点ui到节点vi的路径的异或和。

输出:

  • 对于每次查询,输出路径上节点门的输出异或和。
解决方案

先读入门的信息,并将他们保存在一个二维数组中。在这个数组中,第一列表示输入1,第二列表示输入2,第三列表示门的状态。

n = int(input())
root = int(input())
tree = []

for i in range(n):
    x, y, s = map(int, input().split())
    tree.append([x, y, s])

接下来,我们可以使用一个递归函数来计算查询的异或和。在每一步中,我们检查当前节点的值。如果是根节点,我们可以直接计算根节点门的状态,并递归地调用该函数对子节点执行相同的操作。对于所有其他节点,我们需要首先递归地调用该函数对父节点执行相同的操作,然后计算当前节点门的状态。最后,我们返回当前节点门的状态并计算和之前的结果的异或和。

def xor_path(u, v, xor_sum):
    xor_sum ^= tree[u-1][2]
    if u == v:
        return xor_sum
    if u == root:
        xor_sum = xor_path(min(tree[u-1][0], tree[u-1][1]), v, xor_sum)
    else:
        if tree[u-1][0] != p:
            xor_sum = xor_path(tree[u-1][0], v, xor_sum)
        if tree[u-1][1] != p:
            xor_sum = xor_path(tree[u-1][1], v, xor_sum)
    return xor_sum

q = int(input())

for i in range(q):
    u, v = map(int, input().split())
    p = u
    print(xor_path(u, v, 0))

这个算法的复杂度为O(n+qlogn),其中n为门的数量,q为查询次数。虽然这个算法使用递归,但由于这是一棵树,递归调用的深度最多为树的高度,即logn。因此,总复杂度为O(n+qlogn)。

总结

本题要求计算树上两个节点之间的异或和,这可以通过递归函数来解决。在每个递归步骤中,我们检查当前节点的值,并计算出通过该节点时门的输出。在计算完成后,我们递归地调用函数来计算子节点,并将当前节点的输出异或和上之前的结果。由于这个算法在一次查询中访问所有节点,因此时间复杂度为O(n+qlogn)。