题解:AcWing 848 有向图的拓扑序列

【题目来源】

AcWing:848. 有向图的拓扑序列 - AcWing题库

【题目描述】

给定一个\(n\)个点\(m\)条边的有向图,点的编号是\(1\)\(n\),图中可能存在重边和自环。请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出\(-1\)

若一个由图中所有点构成的序列\(A\)满足:对于图中的每条边\((x,y)\)\(x\)\(A\)中都出现在\(y\)之前,则称\(A\)是该图的一个拓扑序列。

【输入】

第一行包含两个整数\(n\)\(m\)

【输出】

共一行,如果存在拓扑序列,则输出任意一个合法的拓扑序列即可。否则输出\(-1\)

【输入样例】

3 3 
1 2 
2 3
1 3

【输出样例】

1 2 3

【解题思路】

image

【算法标签】

《AcWing 848 有向图的拓扑序列》 #拓扑排序# #BFS#

【代码详解】

#include <bits/stdc++.h>
using namespace std;

const int N = 100010;  // 最大节点数

int n;        // 节点数量
int m;        // 边数量
int h[N];     // 邻接表头数组
int e[N];     // 边的终点数组
int ne[N];    // 下一条边数组
int idx;      // 边的索引
int q[N];     // 队列,用于存储拓扑序列
int d[N];     // 入度数组,d[i]表示节点i的入度

// 添加有向边 a->b
void add(int a, int b)
{
    e[idx] = b;      // 存储边的终点
    ne[idx] = h[a];  // 新边指向原来的第一条边
    h[a] = idx;      // 更新头指针指向新边
    idx++;           // 边索引增加
}

// 拓扑排序函数
// 返回值:true - 存在拓扑序列,false - 存在环
bool topsort()
{
    int hh = 0;      // 队列头指针
    int tt = -1;     // 队列尾指针
  
    // 第一步:将所有入度为0的节点加入队列
    for (int i = 1; i <= n; i++)
    {
        if (!d[i])  // 入度为0
        {
            q[++tt] = i;  // 入队
        }
    }
  
    // 第二步:BFS处理队列中的节点
    while (hh <= tt)  // 队列不为空
    {
        int t = q[hh++];  // 出队
      
        // 遍历节点t的所有邻接点
        for (int i = h[t]; i != -1; i = ne[i])
        {
            int j = e[i];  // 邻接点j
            d[j]--;        // 删除边t->j,j的入度减1
          
            // 如果j的入度变为0,加入队列
            if (d[j] == 0)
            {
                q[++tt] = j;
            }
        }
    }
  
    // 第三步:判断是否所有节点都被处理
    // 如果队列中有n个节点,说明存在拓扑序列
    return tt == n - 1;
}

int main()
{
    // 输入节点数和边数
    cin >> n >> m;
  
    // 初始化邻接表
    memset(h, -1, sizeof(h));
  
    // 读入m条有向边
    for (int i = 0; i < m; i++)
    {
        int a, b;
        cin >> a >> b;
        add(a, b);  // 添加边 a->b
        d[b]++;     // b的入度加1
    }
  
    // 执行拓扑排序
    if (topsort())
    {
        // 输出拓扑序列
        for (int i = 0; i < n; i++)
        {
            printf("%d ", q[i]);
        }
        puts("");  // 换行
    }
    else
    {
        // 存在环,无法进行拓扑排序
        puts("-1");
    }
  
    return 0;
}

【运行结果】

3 3 
1 2
2 3
1 3
1 2 3
posted @ 2026-02-19 15:27  团爸讲算法  阅读(11)  评论(0)    收藏  举报