【图论】输出拓扑序列
导读 ^ _ ^
拓扑序列,简单来说,就是将工程流程一步步输出来。很简单,这一步轮到他,那么它前面一定没有其他任务,也就是入度为0。故选出入度为0的点,就是实现拓扑排序的关键。
何为拓扑序列
- 有向无环图又称为拓扑图
- 是BFS的经典运用
- 拓扑序:在一个有向图中,对所有的节点进行排序,要求没有一个节点指向它前面的节点。
- 有向无环图(DAG)一定有拓扑序列,有向有环图一定没有拓扑序列。
- 出度:从节点出发,有几条边。 出度为零,表示是叶子节点。
- 入度:进入节点,有几条边。 入度为零,表示是根,应该排在拓扑序列最前面的位置。
思路
把入度为0的点放入队列,输出,对其子节点入度减少一
代码实现
技巧:手写队列,这样队列序列就是topsort序列
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
//复杂度 O(n+m)
using namespace std;
const int N = 100010, M = N*2;
int n, m; //点数,边数
int h[N], e[M], ne[M], idx; //邻接表
int d[N]; // d[N]:入度,所有入度为零的点,可以排在当前最前面的位置。
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
int q[N]; //队列以及拓扑序列
bool topsort( ) {
int hh = 0, tt = -1;
for(int i = 1; i <=n; i++)
if(!d[i]) q[++tt] = i;
while(hh <= tt) {
int t = q[hh++];
for(int i = h[t]; i != -1; i = ne[i]) {
int j = e[i];
if(--d[j] == 0) q[++tt] = j;
}
}
return tt == n-1;
}
int main( ) {
memset(h, -1,sizeof h);
cin >> n >> m;
for(int i = 1; i <= m; i++) {
int a, b;
cin >> a >> b;
add(a,b);
d[b]++;
}
if (!topsort()) puts("-1");
else {
//队列次序其实就是拓扑序,这里就充分体现了利用数组模拟队列的优势,queue<int>就麻烦了。
for (int i = 0; i < n; i++) printf("%d ", q[i]);
puts(""); //有向无环图的拓扑序是不唯一的
}
return 0;
}
#谢谢你的观看!
^ _ ^
本文作者:HX-Note
本文链接:https://www.cnblogs.com/HX-Note/p/17204647.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步