📅  最后修改于: 2023-12-03 15:42:13.201000             🧑  作者: Mango
这是一道GATE计算机科学模拟题,题目号为第42题。考察的知识点是图。以下是题目描述:
给定一个无向图,每条边都被标记为红色或蓝色。定义一个关键点是一个节点,它与它的所有邻居都至少有一条红色边。设计一个算法来找出所有的关键点。
输入的第一行包含两个整数n和m,分别代表节点数和边数。接下来的m行中的每一行包含两个整数a和b,表示连通的两个节点的编号。最后一行包含m个整数,代表相应的边的颜色。如果是红色,那么输入1,否则输入0。 这些节点的编号是从1到n的。
输出一个整数,表示关键点的数量。
4 6
1 2
2 3
1 4
2 4
3 4
1 1 0 0 1 1
1
由于要找到关键点,我们需要对于每一个节点都进行遍历,看它是否满足条件。但是直接遍历所有的边和节点的复杂度是O(nm),会超时。所以我们可以使用Tarjan’s algorithm来遍历所有的节点,复杂度为O(n+m)。具体做法是:从一个节点开始,遍历所有相邻节点,并利用dfs来搜索所有的连通子图。对于一个连通子图,我们只需要判断其是否满足条件,即判断它和所有它可能相邻的节点是否满足条件。具体实现可以参考代码:
def dfs(node, G, visited, low, disc, parent, ap):
visited[node] = True
disc[node] = dfs.time
low[node] = dfs.time
dfs.time += 1
children = 0
for neighbor in G[node]:
if visited[neighbor] == False:
children += 1
parent[neighbor] = node
dfs(neighbor, G, visited, low, disc, parent, ap)
low[node] = min(low[node], low[neighbor])
if parent[node] == -1 and children > 1:
ap[node] = True
if parent[node] != -1 and low[neighbor] >= disc[node]:
ap[node] = True
elif neighbor != parent[node]:
low[node] = min(low[node], disc[neighbor])
def findAP(G, n):
visited = [False] * n
disc = [float("inf")] * n
low = [float("inf")] * n
parent = [-1] * n
ap = [False] * n
dfs.time = 0
for i in range(n):
if visited[i] == False:
dfs(i, G, visited, low, disc, parent, ap)
return sum(ap)
本算法的时间复杂度为O(n+m),其中n表示节点数,m表示边数。空间复杂度为O(n),因为需要记录每个节点的信息以及遍历状态。