📌  相关文章
📜  国际空间研究组织 | ISRO CS 2014 |问题 56(1)

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

国际空间研究组织 (ISRO) CS 2014 - 问题 56

这是国际空间研究组织 CS 2014 考试的第 56 个问题。这道问题涉及到了有向图和拓扑排序等知识。

问题描述

给定一个有向无环图 (DAG),请你输出其拓扑排序。

输入格式

输入文件的第一行包含两个整数 $n$ 和 $m$,表示图中有 $n$ 个节点和 $m$ 条边。

接下来 $m$ 行,每行包含两个整数 $a$ 和 $b$,表示存在一条从节点 $a$ 到节点 $b$ 的有向边。

输出格式

输出一行,包含拓扑排序后的节点编号,每个编号之间用空格隔开。如果不存在拓扑排序,则输出 "Sandro fails." (不含引号)。

数据范围

$1 \leqslant n \leqslant 10^5$,

$1 \leqslant m \leqslant 10^6$,

$1 \leqslant a,b \leqslant n$。

样例

输入:

6 6
2 3
3 1
4 1
4 6
5 6
6 1

输出:

4 5 2 3 6 1
题目分析

给定一个有向无环图,要求进行拓扑排序。我们可以使用 Kahn 算法来解决这个问题。

Kahn 算法的基本思想是,从 DAG 中选择一个入度为 0 的顶点并输出,然后删除这个顶点以及以它为起点的所有有向边。重复此过程,直到图中不再存在入度为 0 的顶点为止。如果此时输出的顶点数小于图的顶点数,则说明该图存在环。

Kahn 算法可以使用队列来实现,具体步骤如下:

  1. 统计每个节点的入度。
  2. 将所有入度为 0 的节点加入队列中。
  3. 遍历队列,对于队列中的每个节点,输出该节点,并将以该节点为起点的边的终点入度减 1。如果减去 1 后终点节点的入度变为 0,则将其加入队列中。
  4. 重复步骤 3,直到队列为空。如果输出的节点数小于图的节点数,则说明该图存在环。
代码实现

下面是基于 Python 语言的 Kahn 算法实现代码:

from collections import deque

def topo_sort():
    # 统计每个节点的入度
    in_degree = [0] * (n + 1)
    for a, b in edges:
        in_degree[b] += 1
    
    # 将所有入度为 0 的节点加入队列中
    q = deque()
    for i in range(1, n+1):
        if in_degree[i] == 0:
            q.append(i)
    
    # 输出拓扑排序
    res = []
    while q:
        cur = q.popleft()
        res.append(cur)
        
        for a, b in edges:
            if a == cur:
                in_degree[b] -= 1
                if in_degree[b] == 0:
                    q.append(b)
    
    if len(res) != n:
        return "Sandro fails."
    else:
        return " ".join(map(str, res))

在上面的代码中,nm 分别表示节点数和边数,edges 是一组 (a, b) 值组成的边集合。topo_sort 函数表示进行拓扑排序,并返回排序结果。在函数中,我们首先使用 in_degree 数组统计每个节点的入度,然后将所有入度为 0 的节点加入队列中。在遍历队列的过程中,对于当前节点,我们遍历所有以该节点为起点的边,将终点的入度减 1。如果减 1 后终点的入度变为 0,则将其加入队列中。最后我们判断输出的节点数是否等于图的节点数,如果相等则返回排序结果,否则返回 "Sandro fails."。