当前位置: 首页 > news >正文

拓扑排序-java实现

有向图的拓扑序列

思路
有向无环图一定存在一个拓扑序列,用队列来做,每次存储每个点的入度,拓扑排序的起点是入度为0的点,用队列来解决这个问题,每次发现某点的入度为 0,所以删除该点和该点上所连的边,继续检查入度为0的点,循环(不清楚的可以自己画个图比如 a->b a->c b->d c->d这样的图)。队列顺序就是拓扑排序

queue<-所有入度为0的点
while queue 不空{
取出队头t
枚举t的所有出边 t->j删掉t->j: d[j]--if d[j]==0queue<-j
}

代码

import java.util.*;
public class Main{static int N =  100010,n,m,hh,tt,idx;static int[] e = new int[N],ne = new int[N],h = new int[N];static int[] q = new int[N];static int[] d = new int[N];public static void add(int a,int b){e[idx] = b;ne[idx] = h[a];h[a] = idx++;}public static boolean bfs(){hh = 0 ; tt = -1;for(int i = 1 ; i <= n ; i ++ ){ if(d[i] == 0){     //首先将所有入度为0的点全部插入q队列中q[++tt] = i;}}while(hh <= tt){int t = q[hh++]; //拿出队头for(int i = h[t] ; i != -1; i = ne[i]){ //遍历一下队列中所有的边int s = e[i]; //然后将这个边拿出来d[s] -- ; //将这个边的入度数减1if(d[s] == 0){q[++tt] = s; //如果减完之后s的入度数为0;就将他插入队列中}       }}return tt == n - 1; //最后返回,如果队列中的tt等于n-1个数,说明就是正确的的}public static void main(String[] args){Scanner scan = new Scanner(System.in);n = scan.nextInt();m = scan.nextInt();for(int i = 0 ; i < N ; i ++ ){h[i] = -1; }while(m -- > 0){int a = scan.nextInt();int b = scan.nextInt();add(a,b);d[b] ++;}if(bfs()){//队列刚好队头删除的点就是我们的拓扑序列,因为我们只是将hh往后面移动,但是它具体前面的值还在,直接输出就行for(int i = 0 ; i < n; i ++ ){ System.out.print(q[i] + " ");}}else{System.out.println("-1");}}
}

奇怪的知识增加了 用System.out.printf(q[i] + " ");会超时,写算法的时候尽量用print和println
读取输出更快的写法


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;public class Main {static int N = 100010, idx, hh, tt, n, m;static int[] h = new int[N];static int[] e = new int[N];static int[] ne = new int[N];static int[] d = new int[N]; // 存储每个节点的入度static int[] q = new int[N]; // 数组模拟队列(拓扑排序用)// 邻接表添加边:a → bpublic static void add(int a, int b) {e[idx] = b;ne[idx] = h[a];h[a] = idx++;}// Kahn算法实现拓扑排序public static boolean topsort() {hh = 0;tt = -1;// 所有入度为0的节点入队for (int i = 1; i <= n; i++) {if (d[i] == 0) {q[++tt] = i;}}// 队列不为空时,处理节点while (hh <= tt) {int t = q[hh++]; // 取出队首节点// 遍历该节点的所有邻接节点for (int i = h[t]; i != -1; i = ne[i]) {int j = e[i];d[j]--; // 邻接节点入度减1if (d[j] == 0) { // 入度为0时入队q[++tt] = j;}}}// 若队列长度等于节点数,说明存在拓扑排序(无环)return tt == n - 1;}public static void main(String[] args) throws IOException {// 用BufferedReader替代Scanner,提升输入效率BufferedReader br = new BufferedReader(new InputStreamReader(System.in));StringTokenizer st = new StringTokenizer(br.readLine());// 读取n(节点数)和m(边数)n = Integer.parseInt(st.nextToken());m = Integer.parseInt(st.nextToken());// 初始化邻接表表头为-1(表示空链表)for (int i = 1; i < N; i++) {h[i] = -1;}// 读取m条边,构建邻接表并统计入度while (m-- > 0) {st = new StringTokenizer(br.readLine());int a = Integer.parseInt(st.nextToken());int b = Integer.parseInt(st.nextToken());add(a, b);d[b]++; // b的入度加1}// 执行拓扑排序并输出结果if (topsort()) {// 用StringBuilder拼接输出,避免多次System.out.printStringBuilder sb = new StringBuilder();for (int i = 0; i < n; i++) {sb.append(q[i]).append(" ");}System.out.println(sb.toString().trim());} else {System.out.println(-1);}br.close(); // 关闭流资源}
}
http://www.dtcms.com/a/614921.html

相关文章:

  • 有什么做海报网站ps网页设计作品欣赏
  • 外贸网站建设收款通道崇左网站建设公司
  • 学校部门网站建设WordPress如何添加cnzz
  • ThinkPad 电脑热键修复(静音常亮导致电脑无声音 )
  • 网站数据库怎么做同步吗学院网站模板
  • 宽带技术网网站做亚马逊运营要看哪些网站
  • 淘宝网站怎么做特价做商城网站的公司推荐
  • C语言在线编译 | 高效调试与学习平台
  • 城阳天河小学网站建设版面设计排版
  • 【Python】五.数据容器
  • 做的好的国外网站学电子商务好找工作吗
  • 深圳企业网站制作公司单位网站项目开发流程图
  • 深圳在线制作网站什么做婚车网站最大
  • 南京模板网站建设如何做蛋糕
  • 怎么把自己做的网站放到网上呼叫中心外包公司排名
  • ASC学习笔记0021:移除所有当前属性集并注册传入数组中的属性集
  • 关于Git 提交消息格式错误的分析
  • 坪山附近公司做网站建设多少钱h5网站快速搭建
  • 网站建设功能要求想学服装设计
  • InSTAnT·细胞内空间转录组学分析包
  • AI 十大论文精讲(五):RAG——让大模型 “告别幻觉、实时更新” 的检索增强生成秘籍
  • C++指针与引用的区别详解
  • 比较高度对结构图像的影响
  • 一个账号调用N个AI模型!从LLM到视频生成的丝滑解决方案
  • 宗亲网站开发建设公益网站多少钱
  • 教育学校网站做网站开发中用到的英文单词
  • Qt源码编译记录
  • 智能招聘新范式
  • 伴奏在线制作网站做网站背景全覆盖的代码
  • 深入理解哈希表:实现 unordered_set 与 unordered_map