有向图的拓扑排序以及判断是否有环

拓扑序列是顶点活动网中将活动按发生的先后次序进行的一种排列。 拓扑排序,是对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。

如何求解有向图无环图的拓扑序列?

如何判断一个图是否有环?

848. 有向图的拓扑序列 - AcWing题库

  1. 首先,将入度为0的点入队。
  2. 然后,用宽搜遍历队列。
  3. 将这个点出队,并加入拓扑数组中
  4. 遍历这个点的所有出度
  5. 将其出度点的入度数量减少一
  6. 如果其出度点入度为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;
}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
拓扑排序是一种常用的有向无环图(DAG)排序算法,可用于判断有向图是否存在环。下面是拓扑排序判断有向图是否有环的概要设计: 1. 统计每个节点的入度,入度为 0 的节点加入队列中。 2. 从队列中取出一个入度为 0 的节点,并将该节点从图中删除。 3. 遍历该节点的所有邻居节点,将其入度减 1。 4. 如果有邻居节点入度为 0,则加入队列中。 5. 重复步骤 2-4 直到队列为空。 6. 如果所有节点都被访问过,则说明不存在环;否则存在环。 具体步骤如下: 1. 初始化一个队列 Q,并统计每个节点的入度。 2. 将入度为 0 的节点加入队列 Q 中。 3. 当队列 Q 不为空时,执行以下操作: a. 从队列 Q 中取出一个入度为 0 的节点; b. 将该节点从图中删除; c. 遍历该节点的所有邻居节点,将其入度减 1; d. 如果有邻居节点入度为 0,则加入队列 Q 中。 4. 如果所有节点都被访问过,则说明不存在环;否则存在环。 需要注意的是,如果图中存在环,则无法进行拓扑排序。因此,在实现拓扑排序算法时,需要先判断图中是否存在环,如果存在环,则直接返回有环的结果,否则进行拓扑排序。 总之,拓扑排序是一种非常实用的图算法,可以用于判断有向图是否存在环,也可以用于确定任务的执行顺序和依赖关系等。在实际应用中,我们可以根据具体的问题场景,灵活地运用拓扑排序算法,提高工作效率和准确性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

背水

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值