拓扑排序
拓扑排序
拓扑序列是关于有向图的
拓扑序列:
对于图中的每条边(x, y),x在序列A中都出现在y之前,则称A是该图的一个拓扑序列
也就是说,把图中每一个点按拓扑序排好后,每一个点都是从前指向后的
如果一个图中有环,那么一定没法展成拓扑序
所以我们也称有向无环图为拓扑图
有向图中每一个点有入度和出度
入度:有多少边指向自己
出度:有多少边从这个点出去
因为拓扑序列都是从前指向后的,所以当前所有入度为0的点,都可以排在当前最前面的位置
性质:一个有向无环图,一定至少存在一个入度为0的点
证明:反证法
假设一个一个有向无环图,每一个点的入度都不是0
当往前找到n+1个点是必然存在两个点相同,就构成一个环
所以一个有向无环图,至少存在一个入度为0的点
#include <iostream> #include <cstring> using namespace std; const int N = 100010; int n, m; int h[N], e[N], ne[N], idx; int q[N], d[N]; void add(int a, int b) { e[idx] = b; ne[idx] = h[a]; h[a] = idx ++ ; } 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]; d[j] -- ; if (!d[j]) q[ ++ tt] = j; // 如果入度为0,加入队列 } } return tt == n - 1; // 返回是否存在拓扑序 } int main() { scanf("%d%d", &n, &m); memset(h, -1, sizeof h); for (int i = 0; i < m; i ++ ) { int a, b; scanf("%d%d", &a, &b); add(a, b); d[b] ++ ; // 更新入度 } if (topsort()) // 队列里的次序恰好就是拓扑序 { for (int i = 0; i < n; i ++ ) scanf("%d ", q[i]); printf("\n"); } else { printf("-1\n"); } return 0; }
本文作者:张詠然
本文链接:https://www.cnblogs.com/zyrddd/p/16601257.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步