拓扑排序定义:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。
拓扑排序实现步骤:一个有向无环图,取出入度为0的点,进入到top数组中,删除这个点的同时并且更新它出边的度,不断重复这个操作(取出入度为0的点,进入到top数组中,删除这个点的同时并且更新它出边的度) , 直到这个图上的点都进入到top序列中。 这样讲十分抽象且难懂,这是对图的拓扑排序的拓扑排序模板题链接 ,附有AC代码,理解以后拓扑排序便不是问题;
|
#include<bits/stdc++.h>
using namespace std;
using namespace std;
#define int long long
#define next LXL_NB
const int N = 1e6 + 999 ;
int top[N] , num ; // top 记录图的拓扑排序的值 , num 记录top排序的大小
int e[N] , next[N] , h[N] , idx = 0 ; // 用邻接表存储图
int d[N] ; // 记录每个点的入度
int n , m ; // n 条边 , m 个点 ;
queue<int> q ; // 用来保存入度为 0 的 点
void add(int a,int b)
{
e[idx] = b;
next[idx] = h[a] ; // 把 a ——》 b , a 作为头节点 , 把 a b相连 ;
h[a] = idx ++ ;
}
void solve()
{
for( int i = 1 ; i <= n ; i ++ )
{
if( d[i] == 0 )
{
q.push( i ) ; // 把入度为0的值进入队列中
}
}
while( q.size())
{
int t = q.front() ; // 取出入度为0的值
q.pop() ;
num ++;
top[num] = t ; // 进入top 序列中
for( int i = h[t] ; i != -1 ; i =next[i] ) // 遍历t的出边
{
int j = e[i] ;
d[j] -- ; // 更新出边的入度
if( d[j] == 0)
{
q.push( j ) ; // 入度为 0 的值 ,进入到队列之中 ;
}
}
}
}
signed main()
{
memset( h , -1 , sizeof( h ) ) ;//对邻接表的头节点的值置为 -1;
cin >> n >> m ;
for( int i = 1 ; i <= m ; i ++ )
{
int a, b ;
cin >> a >> b ;
add( a , b ) ;
d[b] ++ ; // a ——> b , b 的入度加1 ;
}
solve( ) ; // 这个函数是对图的拓扑排序的核心代码
if( num < n ) cout << "-1" ;
else
{
for( int i = 1 ; i <= n ; i ++ )
{
cout << top[i] <<" " ; // 输出图的top序列
}
}
return 0 ;
}