📅  最后修改于: 2023-12-03 14:58:20.296000             🧑  作者: Mango
有 $n$ 扇门,每扇门可以是开或关状态。对于每扇门,都有一扇门或多扇门与之相连。给定每扇门与之相连的门的编号,编写程序确定完全打开所有门的最小操作次数。
第一行包含一个整数 $n$,表示有 $n$ 扇门 $(1 \leq n \leq 10^5)$。
接下来 $n$ 行,第 $i$ 行包含一个整数 $m_i$,表示和第 $i$ 扇门相连的门的数量。接下来 $m_i$ 个整数,表示第 $i$ 扇门相连的门的编号 $(1 \leq m_i \leq n)$。每扇门只会在这里被列举一次。
输出一个整数,表示完全打开所有门的最小操作次数。如果所有门都不能完全打开,输出 $-1$。
7
2 2 3
2 4 5
2 6 7
0
1 1
1 1
1 2
2
一个可能的步骤序列如下:1) 开启门 1, 6 和 7。操作次数为 1。2) 开启门 2,3,4 和 5。操作次数为 1。
本题可以使用广度优先搜索(BFS)算法解决。我们可以把每个门看成节点,它所连接到的所有门均可视为这个门的邻居节点。找到每个门的相邻门后,我们可以将其邻居节点塞入队列中。当我们从队列中弹出某个门时,我们将检查是否要打开这个门,如果要打开它,就将产生一次操作。
如果最终所有门都被打开了,我们将返还操作的次数,不然的话我们将返回 -1。
按照上述思路形成的python代码如下:
from collections import deque
n = int(input().strip())
graph = [[] for _ in range(n + 1)]
visited = [False] * (n + 1)
queue = deque()
count = 0
for i in range(1, n + 1):
door = list(map(int, input().strip().split()))[1:]
for d in door:
graph[i].append(d)
queue.append(1)
visited[1] = True
while queue:
u = queue.popleft()
count += 1
for v in graph[u]:
if not visited[v]:
queue.append(v)
visited[v] = True
print(count - 1 if count == n else -1)
上述代码使用邻接列表表示节点之间的关系。时间复杂度为 $O(n+m)$,其中 $n$ 是节点数,$m$ 是边数。空间复杂度为 $O(n+m)$。