📜  门|门CS 2012 |第 48 题(1)

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

题目描述

在一个$n$级门电路中,每一级门所需要的输入(门的“通道”)都已经标好了号,从$1$到$m$。一些输入通道是给定的,还有一些输入通道是给出$x_i$的$i$次方运算后的结果。现在你需要根据这个门电路的输出结果进行模拟推出最终的输出结果。

输入格式

第1行包含三个整数$n$、$m$、$k$,表示电路总共有$n$级,$m$个输入通道,$k$个门电路接口。

第2行包含$m$个整数$x_1, x_2,...,x_m$,表示$m$个输入通道的数值,如果数值为$−1$,表示这个输入没被给定,但它作为一些门接口的输入。

接下来$k$行,每行三个整数$o_1$、$d_1$、$d_2$,表示第$o_1$级门电路的两个输入通道分别连接到$d_1$和$d_2$通道。当一个门电路的两个输入通道都已经连接到某些其他的门接口时,两者的取值关系按照“与运算”的方式进行。

输出格式

输出当$n$级门电路中,每个连通到输出部分的通道的输出值$p_1,p_2,...,p_t$,如果这个值未定义,则输出$-1$。

输入样例
4 6 7
-1 -1 -1 3 4 -1
2 3 4
1 1 2
1 3 4
2 2 2
2 4 5
3 1 1
3 2 3
输出样例
-1
-1
-1
0
说明

上述样例表示一个三级门电路,共有六个输入通道,七个门电路接口。输入通道的编号从$1,2,...,6$。第$4$和$5$个输入通道已经给定数值,其值为$3, 4$。如下图所示:

image-20211024182214207

门电路①的第一次运算结果为与($x_1 < x_2$),门电路②的第一次运算结果为相等($x_3=x_4$),门电路③的第一次运算结果为或($x_1<x_2,x_3=x_4$),输出通道的第一次运算结果为非($x_1<x_2,x_3=x_4$)。

而最终的输出结果就是我们必须要求的。

算法

根据输入的门电路连接情况建立二叉树,再进行DFS遍历,计算并输出结果。

代码
n, m, k = map(int, input().split())

# build tree
edges = [[] for _ in range(n+1)]

for i, v in enumerate(input().split(), 1):
    if v != '-1':
        edges[0].append(i)

for i in range(k):
    a, b, c = map(int, input().split())
    edges[a].append((b, c))


# dfs
res = [-1] * (m+1)

def dfs(u):
    if not edges[u]:
        return -1
    if len(edges[u]) == 1:
        x = dfs(*edges[u][0])
    else:
        x = dfs(*edges[u][0])
        y = dfs(*edges[u][1])
        if u == n:
            return int(x == 1 and y == 0)
        if u < n:
            if x == -1 and y == -1:
                return -1
            if x == -1:
                x = y
            elif y == -1:
                pass
            elif u % 2 == 1:
                x &= y
            else:
                x ^= y
    res[u] = x
    return x

for i in edges[0]:
    dfs(i)

print('\n'.join(str(x) for x in res[1:]))

时间复杂度:$O(n)$。