快去自定义签名吧~|

张詠然

园龄:3年6个月粉丝:3关注:3

拓扑排序

拓扑排序

拓扑序列是关于有向图的

拓扑序列:

对于图中的每条边(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 中国大陆许可协议进行许可。

posted @   张詠然  阅读(27)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起