首先,拓扑排序是将一个图中所有节点排成一个线性序列,使得任意一对节点a和b,在图中a在b的上位,那么在序列中a就在b的前面,这样的序列被称为拓扑序列,因此,拓扑排序只能用于有向无环图,无向图中因为存在环路所以没有拓扑序列。
实现方法:
拓扑序列用一个队列数组储存。
拓扑排序需要用到入度的概念,一个节点的入度就是有其他点指向该点的边的数量,与之相对的还有一个点的出度是指由该点出发的指向其他点的的边的数量。
了解了入度的概念后,我们就知道任意一个入度为0的节点都可以作为拓扑序列的起点。
先将所有入度为0的点入队,然后枚举这些点的出边,再删掉该点,而出边对应的另一个点的入度就减1,在对新得到的入度为0的点进行同样操作,直到所用的点都处理过,最终得到储存了拓扑序列的队列数组。具体的遍历方式用的是图的宽度优先遍历。
主要模板:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1000010;
int h[N],e[N],ne[N],idx,q[N],d[N];//其中q是队列数组,d数组表示每个点的入度
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;//入度为0,队尾存入
while(hh<=tt)
{
int t=q[hh++];//将对头取出存入t另作处理并删除
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
d[j]--;
if(!d[j]) q[++tt]=j;
}
}
return tt==n-1;//当tt=n-1,说明队尾已添加过n次,已将n个数全部遍历,也就代表图存在拓扑序列
}
最后输出队列即可得到图的一个拓扑序列,一个图的拓扑序列不唯一。