图论——拓扑排序

Posted 牧空

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了图论——拓扑排序相关的知识,希望对你有一定的参考价值。

问题描述

设一个有向无环图(DAG),图中有多条有向边 ( U , V ) (U,V) (U,V)。将图中所有的顶点排成一个线性序列,使得在该序列中顶点 U U U都排列在顶点 V V V之前。满足该要求的顶点序列,被称为满足拓扑序列,该过程成为拓扑排序

方法

  1. 从DAG图中选择入度为0的顶点,并输出
  2. 从图中删除该入度为0的顶点及所有以它为起点的边
  3. 重复1和2直到当前图为空,或者图中不存在入度为0的顶点。前者输出的序列为拓扑序列,后者说明图中存在环,没有拓扑序列

例题

题目描述
N N N个比赛队 ( 1 ≤ N ≤ 500 ) (1\\le N \\le 500) (1N500),依次以编号1,2,3…,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即 P 1 P_1 P1 P 2 P_2 P2,用 P 1 , P 2 P_1,P_2 P1,P2表示,排名时 P 1 P_1 P1 P 2 P_2 P2之前。现在请你编写程序确定排名。
输入
输入有若干组,每组中的第一行为两个数N ( 1 ≤ N ≤ 500 ) (1\\le N \\le 500) (1N500)和M;其中N表示队伍的个数,M表示接着有M行的输入数据。接下来的M行数据中,每行也有两个整数 P 1 , P 2 P_1,P_2 P1,P2,表示 P 1 P_1 P1队赢了 P 2 P_2 P2队。
输出
给出一个符合要求的排名。输出时队伍号之间有空格,最后一名后面没有空格。
其他说明:符合条件的排名可能不是唯一的,此时要求输出时编号小的队伍在前;输入数据保证是正确的,即输入数据确保一定能有一个符合要求的排名。

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <queue>


using namespace std;

const int MAXN = 50;

vector<int> graph[MAXN];
int inDegree[MAXN];

vector<int> ToplogicalSort(int n)
{
    vector<int> topology;
    //此处使用优先队列为了满足小序号优先输出的条件
    priority_queue<int, vector<int>, greater<int>> node;
    //先将所有入度为零的节点入队
    for (int i = 1; i <= n; i++)
    {
        if (inDegree[i] == 0)
        {
            node.push(i);
        }
    }
    while (!node.empty())
    {
        // 输出队首,删除节点
        int u = node.top();
        node.pop();
        topology.push_back(u);
        //遍历该节点所指向的其他节点,
        for (int i = 0; i < graph[u].size(); i++)
        {
            int v = graph[u][i];
            //减少入度即除边
            inDegree[v]--;
            //如果该节点的入度为0,则加入队列
            if (inDegree[v] == 0)
                node.push(v);
        }
    }
    return topology;
}

int main(int argc, char const *argv[])
{
    int n, m;
    while (scanf("%d%d", &n, &m) != EOF)
    {
        memset(graph, 0, sizeof(graph));
        memset(inDegree, 0, sizeof(inDegree));
        while (m--)
        {
            int from, to;
            scanf("%d%d", &from, &to);
            graph[from].push_back(to);
            inDegree[to]++;
        }
        vector<int> answer = ToplogicalSort(n);
        for (int i = 0; i < answer.size(); i++)
        {
            if (i == 0)
                printf("%d", answer[i]);
            else
                printf(" %d", answer[i]);
        }
    }

    return 0;
}

以上是关于图论——拓扑排序的主要内容,如果未能解决你的问题,请参考以下文章

图论排序---拓扑排序

图论_拓扑排序

图论基础——邻接链表存图+拓扑排序

图论专题拓扑排序

图论-拓扑排序-应用

操作系统 & 图论传参一个AOE图,得到按其拓扑排序及权值执行临界区代码的线程数组