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

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

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

这是一道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),因为需要记录每个节点的信息以及遍历状态。