/*
有向图的拓扑序列:所有的边的点都是从前指向后的
不是所有有向图都有拓扑序列,eg:有环的有向图,有环就找不到一个入度为0的点
有向无环图一定有拓扑序列,所以有向无环图又称拓扑图,但拓扑图可能不唯一
入度、出度
入度为0的点可以作为起点
*/
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 1e5 + 10;
// n个点,点的编号是 1 到 n
// m条边
int n, m;
// 邻接表存储有向图,模板
int h[N], e[N], ne[N], idx = 0;
// 数组模拟队列
int q[N], hh = 0, tt = -1;
// 存储点i的入度的数量
int d[N];
// 添加边至邻接表,模板
void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx ++;
}
// 是否存在拓扑序列
bool topsort()
{
// 把入度为0的点加入队列
for(int i = 1; i <= n; i++)
{
// 点的编号是 1 到 n
if(d[i] == 0) q[++ tt] = i;
}
// 队列非空
while(hh <= tt)
{
// 取出对头元素
int t = q[hh ++];
// 遍历邻接表,模板
for(int i = h[t]; i != -1; i = ne[i])
{
// 取出指向的点j
int j = e[i];
d[j]--;
// 如果该点的入度为0,就加入队列中
if(d[j] == 0) q[++ tt] = j;
}
}
return tt == n - 1;
}
int main()
{
cin >> n >> m;
memset(h, -1, sizeof h);
memset(d, 0, sizeof d);
// 读入m条边
for(int i = 0; i < m; i++)
{
int a, b;
cin >> a >> b;
// 添加边至邻接表中
add(a, b);
// b的入度加1
d[b] ++;
}
if(topsort())
{
// 遍历队列
for(int i = 0; i < n; i++) printf("%d ", q[i]);
puts("");
}
else puts("-1");
return 0;
}
拓扑排序:848. 有向图的拓扑序列
于 2023-10-29 10:15:26 首次发布