拓扑排序
作者:互联网
目录
定义
拓扑排序的英文名是 Topological sorting。
拓扑排序要解决的问题是给一个图的所有节点排序。
我们可以说 在一个 DAG(有向无环图) 中,我们将图中的顶点以线性方式进行排序,使得对于任何的顶点 到 的有向边 , 都可以有 在 的前面。
还有给定一个 DAG,如果从 到 有边,则认为 依赖于 。如果 到 有路径( 可达 ),则称 间接依赖于 。
拓扑排序的目标是将所有节点排序,使得排在前面的节点不能依赖于排在后面的节点。
来源 拓扑排序-OI Wiki
应用
可以判断图中是否存在环
还可以用来判断图是否是一条链。
Khan算法(BFS)
初始状态下,集合S装着所有入度为0的点,L是一个空列表。
每次从 S中取出一个点 u(可以随便取)放入L , 然后将 u 的所有边 (u,v1),(u,v2)... 删除。对于边 (u,v),若将该边删除后点 v的入度变为 0,则将v 放入S中。
不断重复以上过程,直到集合S为空。检查图中是否存在任何边,如果有,那么这个图一定有环路,否则返回L,L中顶点的顺序就是拓扑排序的结果。
//使用邻接表来储存图
bool topSort()
{
int hh=0,tt=-1;
for(int i=1;i<=n;i++) //将入度为0的点存入队列中
{
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]; //将点i指向j的边删除,j入度也减1
d[j]--;
if(d[j]==0) //如果j入度为0,则将j也入队
q[++tt]=j;
}
}
// 如果所有点都入队了,说明存在拓扑序列;否则不存在拓扑序列。
return tt==n-1;
}
//时间复杂度 O(n+m)O(n+m), nn 表示点数,mm 表示边数
DFS算法
// C++ Version
vector<int> G[MAXN]; // vector 实现的邻接表
int c[MAXN]; // 标志数组
vector<int> topo; // 拓扑排序后的节点
bool dfs(int u) {
c[u] = -1; //表示u已被访问
for (int v : G[u]) { //遍历与点u相连的点
if (c[v] < 0) // 如果子节点比父节点更早访问,说明存在环。
return false;
else if (!c[v])
if (!dfs(v)) return false; 如果子节点未被访问,访问的子节点返回false,则也失败退出
}
c[u] = 1; //恢复现场
topo.push_back(u); //将点u放入队列
return true;
}
bool toposort() {
topo.clear();
memset(c, 0, sizeof(c));
for (int u = 0; u < n; u++)
if (!c[u]) //如果点u入度为0;
if (!dfs(u)) return false;
reverse(topo.begin(), topo.end());//由于递归结果是逆序的,所以需要翻转一下topo
return true;
}
//时间复杂度 O(n+m)O(n+m), nn 表示点数,mm 表示边数
标签:return,int,拓扑,topo,排序,节点 来源: https://www.cnblogs.com/SunAlita/p/15809694.html