图的拓扑排序

拓扑排序定义:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。

拓扑排序实现步骤:一个有向无环图,取出入度为0的点,进入到top数组中,删除这个点的同时并且更新它出边的度,不断重复这个操作(取出入度为0的点,进入到top数组中,删除这个点的同时并且更新它出边的度) , 直到这个图上的点都进入到top序列中。 这样讲十分抽象且难懂,这是对图的拓扑排序的拓扑排序模板题链接 ,附有AC代码,理解以后拓扑排序便不是问题;

  • 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 ;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值