📜  门| GATE CS 2011 |问题17(1)

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

门 | GATE CS 2011 | 问题17

这是一道 GATE CS 2011 中的问题,它考察的是有向图的遍历和拓扑排序。题目描述如下:

给定一个有向图 G,它没有环,且顶点编号从 1 到 n,其中 n 是顶点数。同时给出 m 条边的信息,每条边用它的起点和终点表示,两个整数之间用空格分隔。假设 G 中的所有顶点都可以从顶点 1 到达。针对该有向无环图,编写一个程序,计算它的拓扑排序。

要求将排序结果以一行输出,每个数之间用空格隔开。如果有多个完全相同的解,输出其中任意一个即可。

示例输入
5 4
1 2
1 5
2 3
2 4
示例输出
1 2 4 3 5
实现思路

对于有向无环图,它的拓扑排序实际上就是基于有向边的一个序列,满足在这个序列中,若边 (u, v) 存在,则 u 一定在 v 的前面。可以使用深度优先搜索(DFS)或广度优先搜索(BFS)实现拓扑排序,这里使用 DFS 实现。

首先,需要用一个邻接表(adjacency list)存储有向图的边信息,然后使用一个栈(stack)维护那些还未被访问到的顶点。对于每个未被访问到的顶点,进行一次 DFS 搜索,将它所能到达的所有顶点加入栈中。每个顶点对应的 DFS 搜索完成后,将该顶点从栈中弹出并输出。按照这个顺序输出,就得到了有向图的一个拓扑排序。

代码实现
def topological_sort(n, edges):
    """
    :param n: int, number of vertices
    :param edges: List[Tuple[int, int]], list of edges
    :return: List[int], the topological order of vertices
    """
    # construct adjacency list
    adj_list = [[] for _ in range(n)]
    in_degrees = [0] * n
    for u, v in edges:
        adj_list[u-1].append(v-1)
        in_degrees[v-1] += 1

    # push vertices with in-degree 0 to stack
    stack = [u for u in range(n) if in_degrees[u] == 0]

    # topological sort using DFS and stack
    topo_order = []
    while stack:
        u = stack.pop()
        topo_order.append(u + 1)
        for v in adj_list[u]:
            in_degrees[v] -= 1
            if in_degrees[v] == 0:
                stack.append(v)

    return topo_order

其中 n 是顶点数,edges 是边的信息(每条边用一个二元组表示)。这里使用了邻接表和入度表,以便在 DFS 过程中进行拓扑排序。最后将结果输出即可。

时间复杂度

该算法的时间复杂度为 $O(N + M)$,其中 $N$ 是顶点数,$M$ 是边数。使用邻接表存储和更新图的边信息需要 $O(M)$ 的时间,DFS 遍历需要 $O(N)$ 的时间,因此总复杂度为 $O(N + M)$。时间复杂度在 GATE CS 2011 考试中并不是限制因素,因此可以放心使用。