📜  门| GATE-CS-2014-(Set-2) |问题 6(1)

📅  最后修改于: 2023-12-03 14:58:29.092000             🧑  作者: Mango

介绍GATE-CS-2014-(Set-2)问题 6

题目描述

在一个有向图中,一个路径的割点是指如果这个点被移除掉,则从起点到终点就不能形成可行路径了。你需要编写一个程序,在一个有向图中找到所有的路径割点。

输入
  • 第一行包含两个整数N和M,N为有向图中的节点数,M为边的数量。
  • 接下来M行每行包含两个整数x和y,表示从节点x到节点y的一条有向边。
输出
  • 输出一行,包含整数表示这个有向图中所有的路径割点的数量。
示例
输入
5 6
1 2
2 3
2 4
3 5
4 5
5 2
输出
1
解题思路

这是一个经典的有向图路径割点问题,可以使用Tarjan算法或DFS算法来解决。具体的解题思路如下:

  1. 选择一个起点,并把起点标记为访问过。
  2. 对于该起点,依次访问它的每一个邻接节点。如果当前节点未被访问过,则以该节点为起点做DFS遍历,得到的回溯值和父亲节点作比较,如果回溯值比父亲节点的时间戳小,则说明该节点是路径割点。
  3. 对于起点,如果它有多个子节点,那么它也是路径割点。
代码片段

下面是使用DFS算法来实现该问题的代码片段:

def dfs(u, father, dfn, low, cnt):
    dfn[u] = cnt
    low[u] = cnt
    cnt += 1
    child = 0
    is_cut = False

    for v in adjacent[u]:
        if not dfn[v]:
            child += 1
            dfs(v, u, dfn, low, cnt)
            low[u] = min(low[u], low[v])

            if (not father and child > 1) or (father and low[v] >= dfn[u]):
                is_cut = True
        elif v != father:
            low[u] = min(low[u], dfn[v])

    if is_cut:
        cut_points.append(u)

n, m = map(int, input().split())
adjacent = [[] for _ in range(n)]
dfn = [0] * n
low = [0] * n
cnt = 1
cut_points = []

for _ in range(m):
    x, y = map(int, input().split())
    adjacent[x - 1].append(y - 1)

for i in range(n):
    if not dfn[i]:
        dfs(i, None, dfn, low, cnt)

print(len(cut_points))

代码实现了DFS算法寻找路径割点的过程,其中使用邻接表存储有向图的关系,同时使用DFN和LOW数组来记录每个节点的访问情况和回溯值,最后统计割点个数并输出即可。