拓扑序列是顶点活动网中将活动按发生的先后次序进行的一种排列。 拓扑排序,是对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
如何求解有向图无环图的拓扑序列?
如何判断一个图是否有环?
- 首先,将入度为0的点入队。
- 然后,用宽搜遍历队列。
- 将这个点出队,并加入拓扑数组中
- 遍历这个点的所有出度
- 将其出度点的入度数量减少一
- 如果其出度点入度为0,入队
首先将(入度为0的点)入队,然后出队,依次遍历这个点的出边,删除出边。
删除后呈现这样:
再遍历出边是,如果连接点的入度减为0了,那就将这个点入队。
接着继续出队,遍历b,将b放入数组。
此时变成这样
接着将c入队,并遍历
结果:
接着将d入队,并出队。
最终结果:
#include<iostream>
#include<cstring>
using namespace std;
const int N = 100009;
int h[N],e[N*2],ne[N*2],idx;
int q[N],in_degree[N],hh,tt=-1;
int n,m;
int toplist[N],k=1;//拓扑数组,存路径,k是存储的下标
void add(int a,int b){
e[idx] = b;
ne[idx] = h[a];
h[a] = idx;
idx++;
}
bool topsort(){
for(int i=1;i<=n;i++){ //首先将入度为0的节点入队列
if( !in_degree[i]){
q[++tt] = i;
}
}
while(hh<=tt){ //只要队列非空
int t = q[hh++];//拿出一个入度为0的节点
toplist[k++] = t;
for(int i=h[t];i != -1;i=ne[i]){
int j = e[i];
in_degree[j]--;//不用担心变成负数,如果变成负数说明原来是0,如果是0的话就没有边指向这了。
if( !in_degree[j]){
q[++tt] = j;
}
}
}
return k==n+1;//最后一个入队的时候k也++了,所以要判断k是否等于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);
in_degree[b]++;
}
bool tag = topsort();
if(!tag){
cout<<"-1";
}else{
for(int i=1;i<=n;i++){
cout<<toplist[i]<<" ";
}
cout<<endl;
}
return 0;
}