首页 > 其他分享 >拓扑排序

拓扑排序

时间:2023-07-28 10:36:19浏览次数:33  
标签:int 拓扑 入度 tp 队列 排序

拓扑排序

给定一张有向无环图,排出所有顶点的一个序列A满足:
对于图中的每条有向边(x,y)x在A中的出现都在y之前,则称A是改图的顶点的一个拓扑序。

如图所示,{2 3 5 1 7 4 6},{3 2 1 5 7 6 4}都是合法的拓扑序。

用途:

可以判断有向图中是否有环,可以生成拓扑排序

Kahn算法实现拓扑排序

e[x]存点x的邻点,tp存拓朴序列,din[x]存点x的入度。

算法的核心:

用队列维护一个入度为0的节点的集合。

  • 1.初始化,队列q压入所有入度为0的点的集合.(起始步)
  • 2.每次从q中取出一个点x放入数组tp[]当中
  • 3.然后将x的所有出边删除。若将边(x,y)删除后,y的入度变为0,则将y也压入q中;
  • 4.不断重复2,3过程,直到队列q为空。
  • 5.若tp[]中元素的个数等于n,则有拓扑序;否则,有环.

代码模板如下所示:

vector<int> e[N],tp;
int din[N];

bool topsort()
{
    queue<int>q;//维护入度为零的点
    for(int i=1;i<=n;i++)
    if(din[i]==0)q.push(i);
    while(q.size())//只要队不空,就从队头取出一个元素弹出
    {
        int x=q.front();
        q.pop();
        tp.push_back(x);//将取出的元素压入tp数组
        for(auto y:e[x])
        {
            if(--din[y]==0)q.push(y);//判断每次减一的时候入度有没有变为0
        }
    }
    return tp.size()==n;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<m;i++)
    {
        cin>>a>>b;
        e[a].push_back(b);//压入a的临点b
        din[b]++;//同时b的入度要加 1
    }
    if(!topsort())puts("-1");//有环无解
    else for(auto x:tp)printf("%d ",x);//迭代循环输出
    return 0;
}

DFS实现拓扑排序

e[x]存x的临点,tp存拓扑序列,c[x]存点的颜色
算法的核心是变色法,一路搜索一路给点进行变色,如果有拓扑排序,每个点的颜色都会从0 -> -1 ->1,经历3次变色

  • 1.初始状态所有的状态都染色为0;
  • 2.枚举每个点,进入x点,就把x染色为-1.然后,枚举x的儿子节点y,如果y的颜色为0,说明没碰过该点,进入y继续走
  • 3.如果枚举完x的儿子,没发现环,则x染色为1,并把x压入tp数组
  • 4.如果发现有个熊孩子的颜色为-1,说明回到了祖先节点,发现了环,则一路返回false,退出程序.

代码模板如下所示:

vector<int> e[N],tp;
int c[N];//染色数组

bool dfs(int x)
{
    c[x]=-1;
    for(int y:e[X])
    {
        if(c[y]<0)return 0;//有环
        
        else if(!c[y])
        if(!dfs(y))return 0;
    }
    c[x]=1;
    tp.push_back(x);
    return 1;
}

bool topsort()
{
    memset(C,0,sizeof(c));
    for(int x=1;x<=n;x++)
    {
        if(!c[x])
            if(!dfs(x))return 0;
    }
    reverse(tp.begin(),tp.end());
    return 1;
}

总结

  • Kahn算法 队列维护,顺着拓扑收集点
  • dfs算法,系统栈维护,逆着拓扑序收集点
  • 时间复杂度:O(E+V)
  • 不连通:不影响拓扑排序
  • 求字典序的最小拓扑序,将Kahn算法中的队列替换为优先队列(小根堆)
    时间复杂度为O(E+VlogV)

标签:int,拓扑,入度,tp,队列,排序
From: https://www.cnblogs.com/OhLonesomeMe/p/17586900.html

相关文章

  • P2127 序列排序 题解
    原题题目意思\(有一个数列a,每次可以挑选任意两个元素交换位置,代价为这两个元素的和,问把序列a升序排序所需的最小总代价\)\(定义数列上的一个有i个元素的环S使得s_1要换到s_2,s_2要到s_3,……,s_i要到s_1\)\(原图一个元素只有一个目标位置,所以可以看作一个有n点,n边的有向图\)......
  • 虚拟机 NAT网络拓扑
    摘要目的:介绍虚拟机linux的NAT网络结构虚拟机网络结构分析:实际上,主机是开设了一个网卡,即vmnet8,这个网卡为主机开了一个虚拟网络而这个网卡也就是虚拟网络的出口,虚拟网络通过这个网卡实现网络地址转换要求,vmnet8和linux虚拟机在一个网段,也就是前面三位要相同具体地可......
  • C语言快速排序及其优化操作
    快速排序原理简述:找到每一轮最大(最小)的数,依次从左到右存入新的数组,就完成了降序(升序)的排列。#include<stdio.h>intmain(void){intn;scanf("%d",&n);inta[n],temp;for(inti=0;i<n;i++){scanf("%d",&a[i]);}for(......
  • 2023-07-27:最长可整合子数组的长度, 数组中的数字排序之后,相邻两数的差值是1, 这种数组
    2023-07-27:最长可整合子数组的长度,数组中的数字排序之后,相邻两数的差值是1,这种数组就叫可整合数组。给定一个数组,求最长可整合子数组的长度。答案2023-07-27:算法maxLen的过程如下:1.检查输入数组是否为空,如果为空,则返回0,表示最长可整合子数组长度为0。2.初始化长度为1的最长......
  • Java 对json排序
    Java对JSON排序在日常的开发中,我们经常需要将JSON数据进行排序,以满足业务需求或者提高查询效率。本文将介绍如何使用Java对JSON数据进行排序,并提供示例代码帮助理解。什么是JSON?JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式,常用于前后端数据传输。它以......
  • P8859 冒泡排序
    我回来了。参考:https://www.luogu.com.cn/blog/_post/509374、https://www.luogu.com.cn/blog/_post/510710。考虑type1,注意到\(1\)是不能被超越的,且一个数操作多次不优,因此第一步操作\(1\)不劣。因此从小到大归位每个数不劣,答案即为总数减去前缀\(\max\)的数目。从小到......
  • linux查询tcp连接数并排序
    查询已连接[root@rabbitmq-1rabbitmq]#netstat-an|awk'{print$5}'|cut-d:-f1|sort|uniq-c|sort-rn3393172.16.229.2532995172.16.47.212400172.16.229.232186172.16.229.254149172.16.229.240102172.16.229.218这个......
  • Java十大经典排序算法汇总
    以下是十大经典排序算法:冒泡排序(BubbleSort):比较相邻两个元素,如果逆序则交换,重复多轮,直到无逆序情况。选择排序(SelectionSort):在待排序元素中选择最小(大)元素,放在已排序序列的起始位置,重复多轮,直到所有元素有序。插入排序(InsertionSort):从第二个元素开始,将每个元素插入到已排序......
  • 后缀排序
    后缀排序本文做复习用,不宜初学用。定义\(sa\)表示排名为\(i\)的位置。\(rk\)表示位置为\(i\)的排名。\(y\)表示按照第二关键字排序排名为\(i\)的位置。\(height\)表示排名为\(i\)和\(i-1\)的后缀的最大前缀\(h\)表示位置为\(i\)和它排名前一位的后缀......
  • sort排序
    数值排序: arr.sort((a,b)=>a.id-b.id); 字符串排序:varcompare=function(a,b){      if(a.name<b.name){        return-1;      }elseif(a.name>b.name){        return1;   ......