📅  最后修改于: 2023-12-03 15:12:43.034000             🧑  作者: Mango
本题是GATE-CS-2016(Set 1)的第20题,主要考察了程序员对于有向图的遍历和拓扑排序的掌握程度。
一个城市公交车系统中,一些公交线路经过一些城市,并形成一个有向图。城市的编号使用 $1$ 到 $n$ 之间的整数表示,该图中有 $n$ 个节点和 $m$ 条边。每个节点上都有一张照片。当你保安检查过去时,你只能进入那些与你手中照片相同的城市。我们想确定有多少个城市可以被访问。可以假设图是强连通的。
函数签名如下:
def count_accessible_cities(n, m, edges, photos):
pass
输出一个整数,表示有多少个城市可以被访问。
5 5
1 2
2 3
3 1
3 4
5 3
1 0 0 0 5
3
本题要求我们在一个有向图中,找到能够被访问的城市数量,我们可以采用如下的算法:
from collections import deque
def count_accessible_cities(n, m, edges, photos):
visited = [False] * (n + 1)
in_degree = [0] * (n + 1)
# 遍历所有的边,并计算每个节点的入度
for u, v in edges:
in_degree[v] += 1
# 把所有照片编号为 0 的城市的 visited 置为 True
for i in range(1, n + 1):
if photos[i - 1] == 0:
visited[i] = True
queue = deque([])
# 将所有入度为 0 的节点加入队列中
for i in range(1, n + 1):
if in_degree[i] == 0:
queue.append(i)
visited_count = 0
# 进行拓扑排序,更新 visited_count 的值
while queue:
u = queue.popleft()
visited[u] = True
visited_count += 1
for v in range(1, n + 1):
if not visited[v] and in_degree[v] > 0:
in_degree[v] -= 1
if in_degree[v] == 0:
queue.append(v)
# 遍历图,更新 visited_count 的值
for i in range(1, n + 1):
if visited[i]:
visited_count += 1
return visited_count
# sample test
print(count_accessible_cities(5, 5, [(1, 2), (2, 3), (3, 1), (3, 4), (5, 3)], [1, 0, 0, 0, 5]))
通过拓扑排序,我们每遍历一个节点一次,就可以把它从图中删除,并将与其相邻的节点入度减一。在最坏情况下,我们需要遍历图中所有的节点和边,时间复杂度为 $O(n+m)$。