拓扑排序-java

主要通过宽度优先搜索(BFS)来实现有向无环图的拓扑序列,邻接表存储图。数组模拟单链表、队列,实现BFS基本操作。

文章目录

前言

一、有向图的拓扑序列

二、算法思路 

 1.拓扑序列

2.算法思路

三、使用步骤

1.代码如下(示例):

2.读入数据:

3.代码运行结果

总结


前言

主要通过宽度优先搜索(BFS)来实现有向无环图的拓扑序列,邻接表存储图。数组模拟单链表、队列,实现BFS基本操作。


提示:以下是本篇文章正文内容,下面案例可供参考

一、有向图的拓扑序列

给定一个 n 个点 m 条边的有向图,点的编号是 1 到 n,图中可能存在重边和自环。

请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出 −1。

若一个由图中所有点构成的序列 A 满足:对于图中的每条边 (x,y),x 在 A 中都出现在 y 之前,则称 A 是该图的一个拓扑序列。

输入格式

第一行包含两个整数 n 和 m。

接下来 m 行,每行包含两个整数 x 和 y,表示存在一条从点 x 到点 y 的有向边 (x,y)。

输出格式

共一行,如果存在拓扑序列,则输出任意一个合法的拓扑序列即可。

否则输出 −1。

数据范围

1≤n,m≤100000

二、算法思路 

 1.拓扑序列

图1.1拓扑序列示例 

有向图的拓扑排序是指将有向无环图(DAG)中的所有顶点排成一个线性序列,使得对于图中的每一条有向边 (u, v),顶点 u 在序列中都出现在顶点 v 的前面。换句话说,如果图中存在一条从顶点 u 到顶点 v 的有向边,那么在拓扑排序中顶点 u 将在顶点 v 的前面。

在有向图中,每个顶点都有两种相关的度量:入度(in-degree)和出度(out-degree)。这些度量用于描述有向图中顶点之间的关系。

  • 入度:一个顶点的入度是指指向该顶点的边的数量。换句话说,对于顶点v,它的入度是有多少条边以v为终点。

  • 出度:一个顶点的出度是指从该顶点发出的边的数量。换句话说,对于顶点v,它的出度是有多少条边以v为起点。

各结点出入度示例
结点入度出度
102
211
320

一个有向无环图一定至少存在一个入度为0的点。 

开始入度为0的结点都是初始结点,然后当我们打印该结点,就将它指向的结点的入度擦去,然后我们在找入度为0的结点当作下一个结点重复上述操作,我们就可以得到该有向无环图的拓扑序列。

本次用宽度优先搜索来实现有向图的拓扑序列!

注:有向无环图才有拓扑序列,无向图是没有的。

2.算法思路

我们采用宽度优先搜索来实现上述操作。我们还是用邻接表法来存储图。我们还是用一维整型数组head,其中head[i]表示结点i相连的边,对应的边用单链表存储;还是用数组来模拟单链表,一维整型数组e用来存储结点的值,一维整型数组存储该结点指向的下一结点在e数组中的索引,整型变量index表示新创建的结点在e数组中的索引。

 添加a指向b边我们只需要在head数组中对应结点 a 的单链表中插入结点 b 即可。单链表的插入具体细节请看这篇博客单链表-java-CSDN博客。

    public static void add(int a, int b){e[index] = b;ne[index] = head[a];head[a] = index++;}

数组模拟单链表是基础!!! 

我们引入一个一维整型数组d,来存储图中每个点的入度;一维整型数组queue来模拟队列,整型变量hh时队头指针,整型变量rear时队尾指针。当这个点的入度为0时,我们就把它当作拓扑序列的起点,放入队列;当队列不为空时,我们弹出一个结点即t = queue[hh++];我们来遍历与结点 t相连的点,找到与结点 t 相连的点 j ,将结点 j 对应的入度减1 即 d[j]--;如果该结点的入度为0的话,就说明该结点没有上一个结点指向它,我们就让它入队。当队列为空时,如果我们的队尾指针等于n -1 的话就说明我们已经找出对应的拓扑序列。如果图中存在环的话,那么我们我们的队列为空的时候,队尾指针根本不可能到 n-1,一定比这个值小。

拓扑序列的本质就是我们每次把入度为0的结点打印出来,然后该结点指向的所有的结点的入度减1,然后再打印入度为0的结点。

所以拓扑排序就是对应队列数组从0到n - 1打印即可。

三、使用步骤

1.代码如下(示例):


import java.io.*;
import java.util.Arrays;public class Main {static PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));static StreamTokenizer st = new StreamTokenizer(br);static int n,m;static int N = 100100;static int[] head = new int[N];static int[] e = new int[N];static int[] ne = new int[N];static int index;//存储每个点的入度static int[] d = new int[N];static int[] queue = new int[N];public static void main(String[] args) throws Exception{n = nextInt();m = nextInt();Arrays.fill(head,-1);while (m-- > 0){int a = nextInt();int b = nextInt();add(a,b);d[b]++;}if(topSort()){for(int i = 0;i < n;i++){pw.print(queue[i]+" ");}}else {pw.println("-1");}pw.flush();}public static boolean topSort(){int hh = 0;int rear = -1;//将起点放入队列for(int i = 1;i <= n;i++){if(d[i] == 0){queue[++rear] = i;}}while (hh <= rear){int t = queue[hh++];for(int i = head[t]; i != -1;i = ne[i]){//t指向jint j = e[i];d[j]--;if(d[j] == 0){queue[++rear] = j;}}}return rear == n - 1;}public static void add(int a, int b){e[index] = b;ne[index] = head[a];head[a] = index++;}public static int nextInt()throws Exception {st.nextToken();return (int)st.nval;}
}

2.读入数据:

3 3
1 2
2 3
1 3

3.代码运行结果

1 2 3 

总结

上述主要通过宽度优先搜索来实现有向无环图的拓扑序列,其中还是很常用的邻接表存储图。数组模拟单链表、队列,然后宽度优先搜索3部曲,大致就这些。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/25967.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大模型实战-【Langchain4J中Using AI Services in Spring Boot Application②】

Using AI Services in Spring Boot Application LangChain4j Spring Boot starter greatly simplifies using AI Services in Spring Boot applications. @SystemMessage Now, let’s look at a more complicated example. We’ll force the LLM reply using slang 😉 Th…

QT 使用资源文件的注意点

不要存放没有使用的资源文件 即使在代码中没有使用到的资源文件&#xff0c;也会编译到执行文件或者DLL里面去这样会增大它的体积。如下 在代码没有使用这个资源文件(10.4M的2k图片)&#xff0c;但是编译出来的程序有 12M左右的大小 1 假设我们有一个比较复杂的项目&#…

Web前端学习之路:深入探索学习时长与技能进阶的奥秘

Web前端学习之路&#xff1a;深入探索学习时长与技能进阶的奥秘 在数字化时代&#xff0c;Web前端技术成为了连接用户与互联网世界的桥梁。对于初学者来说&#xff0c;学习Web前端究竟需要多久&#xff0c;以及如何高效掌握相关技能&#xff0c;一直是困扰他们的难题。本文将从…

ReentrantLock底层原理

ReentrantLock public ReentrantLock() {sync new NonfairSync(); }public ReentrantLock(boolean fair) {sync fair ? new FairSync() : new NonfairSync(); }ReentrantLock 的默认实现是非公平锁&#xff0c;实际上 ReentrantLock 中的方法&#xff0c;几乎都让 sync 实现…

springboot高校运动会信息管理系统设计与实现-计算机毕业设计源码92968

摘 要 本论文介绍了一个高校运动会信息管理系统的设计和实现过程。首先是高校运动会的需求分析和可行性分析&#xff0c;通过比较运动会的各个工作流程&#xff0c;确定了系统的数据流程和数据库结构&#xff0c;然后介绍了高校运动会信息管理系统开发所使用的软件开发工具&…

Java实现数据结构——顺序表

目录 一、前言 二、实现 2.1 增 2.2 删 2.3 查 2.4 改 2.5 销毁顺序表 三、Arraylist 3.1 构造方法 3.2 常用操作 3.3 ArrayList遍历 四、 ArrayList具体使用 4.1 杨辉三角 4.2 简单洗牌算法 一、前言 笔者在以前的文章中实现过顺序表 本文在理论上不会有太详细…

TCP是如何保证可靠传输的

TCP&#xff08;传输控制协议&#xff09;通过多种机制来保证数据的可靠传输&#xff0c;以下是TCP确保可靠性的主要特点&#xff1a; 数据包编号&#xff1a; TCP给每个字节的数据分配一个序号&#xff0c;确保数据能够按照正确的顺序被接收。 确认应答&#xff08;ACK&#x…

vscode侧边栏错乱重制

vscode 重制命令面板 View: Reset View Locations

13_1 Linux 邮件服务与NTP时间服务

13_1 Linux 邮件服务与NTP时间服务 文章目录 13_1 Linux 邮件服务与NTP时间服务[toc]1. 邮件服务器2. NTP时间服务器 1. 邮件服务器 邮件服务器的作用&#xff1a; 为用户提供电子邮箱存储空间&#xff08;用户名邮件域名&#xff09;处理用户发出的邮件 —— 传递给收件服务器…

三星系统因何而成?或许是因为吞噬了第四颗恒星

相比于其他的类似星体&#xff0c;这个特殊的三星系统拥有更大更紧密的星体。 三星 天文学家发现了前所未见的三星系统。相比于其他典型的三星系统&#xff0c;这一三星系统拥有更大的体积&#xff0c;并且排列也更加紧密&#xff0c;这也使得这一系统更加特别。科学家推测&am…

【题解】—— LeetCode一周小结23

&#x1f31f;欢迎来到 我的博客 —— 探索技术的无限可能&#xff01; &#x1f31f;博客的简介&#xff08;文章目录&#xff09; 【题解】—— 每日一道题目栏 上接&#xff1a;【题解】—— LeetCode一周小结22 3.分糖果 II 题目链接&#xff1a;1103. 分糖果 II 排排坐…

MySQL-数据处理(1)

029-数据处理函数之获取字符串长度 select length(我是Cupid); select char_length(我是Cupid);concat (concatenate) select concat(cu, pid, so, handsome);030-去除字符串前后空白-trim select trim( a b c );select trim(leading 0 from 000110); select t…

C++设计模式---策略模式

1、介绍 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为设计模式&#xff0c;它使你能在运行时改变对象的内部算法。策略模式定义了一系列的算法&#xff0c;并将每一个算法封装起来&#xff0c;使它们可以互相替换。策略模式使得算法可以独立于使用它的客户端变…

USB转I2C转SPI芯片CH341

CH340与CH341区别 CH340主要用于将USB转换为各种串口&#xff0c;CH340H和CH340S可以实现USB转并口。 CH341和340的不同之处在于CH341提供I2C和SPI接口&#xff0c;方便连接到I2C或SPI总线操作相关的器件。 CH341主要有6种封装。见表1. CH341T SSOP-20封装和丝印 USB 总线转接…

【服务实现读写分离】

文章目录 什么是读写分离基于Spring实现实现读写分离项目中常用的数据源切换依赖包 什么是读写分离 服务读写分离&#xff08;Service Read-Write Splitting&#xff09;是一种常见的数据库架构设计模式&#xff0c;旨在提高系统的性能和可扩展性。通过将读操作和写操作分离到…

分布式事务AP控制方案(上)

分布式事务控制方案 本篇文章给出一种要求高可用性&#xff08;AP思想&#xff09;的分布式事务控制方案 下篇新鲜出炉&#xff1a;点我查看 分布式事务控制方案1、业务背景2、本地消息表的设计3、对消息表的操作4、任务调度5、任务流程控制的抽象类6、课程发布的实现类7、总…

[力扣题解] 236. 二叉树的最近公共祖先

题目&#xff1a;236. 二叉树的最近公共祖先 思路 代码 用深度搜索的思想&#xff08;好吧&#xff0c;前序、中序、后序都是深搜思想&#xff09;&#xff0c;保存寻找路径&#xff0c;看看找到2个节点的路径的重合部分&#xff0c;就可以找到最近公共祖先&#xff1b; /*…

代理IP使用api接

代理IP使用API接口&#xff0c;通常是指通过API接口获取代理IP地址&#xff0c;并将其应用于爬虫、数据采集、反爬虫等场景中&#xff0c;以提高数据采集效率和保护数据采集安全。 一般来说&#xff0c;代理IP提供商会提供API接口文档和SDK供开发者使用。你需要先注册并登录代…

硬件工程师的蜗牛成长路

一名合格的硬件工程师&#xff0c;需要掌握的知识有很多&#xff0c;知识点积累不是一蹴而就&#xff0c;而是细水长流&#xff0c;螺旋提升&#xff0c;不急&#xff0c;慢慢来&#xff0c;想掌握的都能掌握&#xff0c;就让时间来见证个人的成长路径。 ---大青山 2024/6/10 …

diffusers 再次继续训练LoRA时,如何导入已有的LoRA权重

我们通常会有微调扩散模型的需求&#xff0c;比如对LoRA进行训练来实现对Stable diffusion模型的微调。 但是有时候我们需要复用先前训练好的LoRA参数来继续进行训练。此时并不需要我们重新使用API向U-Net网络加载LoRA对应的adapter参数权重&#xff0c;我们可以直接通过diffu…