【拓扑排序】|图论|基于BFS / DFS 的拓扑排序 |出度入度

1,拓扑排序的概念

拓扑排序是指对有向无环图(DAG)进行排序的一种算法。实际上就是对图内结点的优先级的排序过程,同一个优先级的前后排序不用纠结,本质上是都可以的。

拓扑排序的求解过程:
我们需要了解一些基础知识 首先是出入度的概念

出度: 这个点作为起点的单向边的数量
入度: 这个点作为终点的单向边的数量

2, BFS的拓扑序列的实现

无论是那种操作都是BFS和图的建立操作的结合

1, BFS实现拓扑序列有两种办法

第一种首先我们要从出度为0的开始,创建入度数组进行正序搜索.

算法思路
这个算法是一个图的序列,第一步我们要完成对图的存储操作 ,我们选用最简单的图的存储的操作,
邻接表存储 使用创建边的操作来完成对树的存储。

第二步就是BFS的过程,首先我们要处理初始结点,我们遍历一边所有的结点,把所有结点入度为零的都存入队列,完成BFS的第一步操作。然后我们只要依次的找到,队列中结点中的下面的结点,然后我们就对这些结点完成减去入度 的操作,再把度数为0的点压入队列,当队列为空的时候就完成了队列的提取。

注意 我们使用的队列为模拟队列,因为我们在后面要完成队列的输出,使用STL中的队列元素会导致这个队列元素无法输出,所以我们不选用他 .

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std ;

const int N = 1e5 + 10 ;

int n , m ; 
int ne[N] ,e[N] ,idx , h[N] ;
int re_p[N] ;
int q[N] ;
void add(int a ,int b )
{
    
    
   e[++ idx ] = b ,ne[idx] = h[a] , h[a] = idx ;
}

bool topsort ()
{
    
    
   int tt = - 1 , hh = 0 ;
   for(int i = 1 ; i <= n ; i ++ )
   {
    
    
   	 if(!re_p[i])
   	 	q[++ tt ] = i ; 
   }
   while ( hh <= tt )
   {
    
    
   	int  t = q[hh] ;
   	hh ++ ; 
   	for(int i = h[t] ; i != - 1 ; i = ne[i])
   	{
    
    
   		int x = e[i] ;
   		if(-- re_p[x] == 0)
   			q[++ tt] = x ;
   	}
   }
   return tt == n - 1 ; 
}

int main ()
{
    
    	
   memset( h , - 1 ,sizeof h ) ;
   cin >> n >> m ;
   for(int i = 0 ; i < m ; i ++ )
   {
    
    
   	int a, b ;
   	cin >> a >> b ;
   	add(a , b ) ;
   	re_p[b] ++ ;
   }
   if(!topsort())
   	cout << -1 ;
   else 
   	for(int i = 0 ;i < n ; i ++ )
   		cout << q[i] << " ";
   	cout << endl ; 
   return 0 ;
}

第二种思路: 从出度来思考,首先这种做法是不赞同的。由于用出度来作为标准,我们需要一个回溯的过程,也就是要么我们直接建立一个往回的反向边,要么我们就要多加一个其他的回溯方式,大致思路相同,不过更加难思考。

不推荐
不推荐
不推荐


#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std ;

const int N = 1e5 + 10 ;

int n , m ; 
int ne[N] ,e[N] ,idx , h[N] ;
int re_p[N] ;
int q[N] ;
void add(int a ,int b )
{
    
    
	e[++ idx ] = b ,ne[idx] = h[a] , h[a] = idx ;
}

bool topsort ()
{
    
    
	int tt = - 1 , hh = 0 ;
	for(int i = 1 ; i <= n ; i ++ )
	{
    
    
		 if(!re_p[i])
		 	q[++ tt ] = i ; 
	}
	while ( hh <= tt )
	{
    
    
		int  t = q[hh] ;
		hh ++ ; 
		for(int i = h[t] ; i != - 1 ; i = ne[i])
		{
    
    
			int x = e[i] ;
			if(-- re_p[x] == 0)
				q[++ tt] = x ;
		}
	}
	return tt == n - 1 ; 
}

int main ()
{
    
    	
	memset( h , - 1 ,sizeof h ) ;
	cin >> n >> m ;
	for(int i = 0 ; i < m ; i ++ )
	{
    
    
		int a, b ;
		cin >> a >> b ;
		add(b , a ) ;
		re_p[a] ++ ;
	}
	if(!topsort())
		cout << -1 ;
	else 
		for(int i = n - 1 ;i >= 0 ; i -- )
			cout << q[i] << " ";
		cout << endl ; 
	return 0 ;
}

3,DFS和拓扑序列

算法思路
DFS的递归思想在这个拓扑序列中的表现也是非常优越的,一般DFS和BFS的第二种思想也是根据出度为零来进行计算的所以说这种实现方式实际上不推荐,但是可以实现,首先是实现的方式,由于DFS是嵌套递归的思想,所以选择的出度分割点的思想。

猜你喜欢

转载自blog.csdn.net/wen030803/article/details/131901205