该代码实现了拓扑排序,其运行流程如下:

  1. 初始化邻接表和计数器。

  2. 读入节点数和边数,并根据读入的边信息构造有向图,同时统计每个节点的入度。

  3. 将所有入度为0的节点入队,开始进行拓扑排序。

  4. 不断从队列中取出节点,将其所有邻接节点的入度减1。

  5. 如果某个邻接节点的入度变为0,则将其入队。

  6. 重复步骤4和步骤5,直到队列为空。

  7. 判断所有节点的入度是否都为0。如果是,则说明有拓扑序;否则,说明存在环。

  8. 如果有拓扑序,输出'Yes';否则,输出'No'。

该代码的时间复杂度为O(n+m),其中n为节点数,m为边数。

#include <iostream>
#include <vector>
#include <queue>

using namespace std;

const int N = 100010; // 用来表示节点数的最大值

int h[N], e[N], ne[N], idx;
int d[N]; // 存储每个节点的入度
int n, m; // n表示节点数,m表示边数

void add(int a, int b) // 建立有向图的邻接表
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

bool topsort() // 实现拓扑排序
{
    queue<int> q;
    for (int i = 1; i <= n; i ++ )
        if (!d[i]) // 将所有入度为0的节点入队
            q.push(i);

    while (q.size())
    {
        int t = q.front();
        q.pop();
        for (int i = h[t]; ~i; i = ne[i])
        {
            int j = e[i];
            if (-- d[j] == 0) // 将与当前节点相关联的节点的入度减1
                q.push(j); // 如果减1后该节点的入度为0,则将其入队
        }
    }

    for (int i = 1; i <= n; i ++ )
        if (d[i]) // 如果还有入度不为0的节点,则说明存在环
            return false;

    return true;
}

int main()
{
    //初始化计数器,使用邻接表存储有向图
    memset(h, -1, sizeof h);
    cin >> n >> m;

    // 构造有向图
    while (m -- )
    {
        int a, b;
        cin >> a >> b;
        add(a, b);
        d[b] ++ ;
    }

    // 判断是否有拓扑序 
    if (topsort())
        puts("Yes");
    else
        puts("No");

    return 0;
}

该代码使用邻接表来存储有向图,并通过队列来实现拓扑排序。代码首先初始化邻接表和入度数组,然后根据输入的边信息构造有向图并统计每个节点的入度。接着将所有入度为0的节点入队,并不断从队列中取出节点,将其所有邻接节点的入度减1。如果某个邻接节点的入度变为0,则将其入队。重复该过程,直到队列为空。最后判断所有节点的入度是否都为0,如果是,则说明有拓扑序;否则,说明存在环。

代码的时间复杂度为O(n+m),其中n为节点数,m为边数。该代码对于理解和实现拓扑排序算法具有参考价值。

C++ 拓扑排序算法实现及代码解析

原文地址: https://www.cveoy.top/t/topic/oJyQ 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录