U107394 拓扑排序模板

题目描述

有向无环图上有 n n n 个点, m m m 条边。求这张图字典序最小的拓扑排序的结果。字典序最小指希望排好序的结果中,比较靠前的数字尽可能小。

输入格式

第一行是用空格隔开的两个整数 n n n m m m,表示 n n n 个点和 m m m 条边。
接下来是 m m m 行,每行用空格隔开的两个数 u u u v v v,表示有一条从 u u u v v v 的边。

输出格式

输出一行,拓扑排序的结果,数字之间用空格隔开

样例 #1

样例输入 #1

5 3
1 2
2 4
4 3

样例输出 #1

1 2 4 3 5

提示

1 ≤ n , m ≤ 1 0 5 1 \leq n,m \leq 10^5 1n,m105
注意:图上可能有重边

思路

拓扑排序是一种对有向无环图(DAG)进行排序的算法,它可以将 DAG 中的顶点排序,使得对于任意一对顶点 u u u v v v,如果 u u u v v v 之前,则不存在从 v v v u u u 的路径。

拓扑排序的算法有很多种,这里介绍一种基于小根堆的拓扑排序算法。

算法步骤

  1. 初始化一个小根堆,将所有入度为 0 0 0 的顶点入堆。
  2. 从小根堆中取出一个顶点,并将其输出。
  3. 对于该顶点的所有出边,将出边的终点的入度减 1 1 1
  4. 如果某个顶点的入度变为 0 0 0,则将其入堆。
  5. 重复步骤 2 − 4 2-4 24,直到小根堆为空。

时间复杂度

O ( V + E ) O(V+E) O(V+E),其中 V V V 是顶点数, E E E 是边数。

空间复杂度

O ( V ) O(V) O(V),其中 V V V 是顶点数。

代码实现

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StreamTokenizer;
import java.util.Arrays;
import java.util.PriorityQueue;
public class Main {
	static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
	static PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));
	static StreamTokenizer sr = new StreamTokenizer(in);
	static int MAXN = 100001;
	static int MAXM = 100001;
	// 建图链式前向星
	static int[] head = new int[MAXN];
	static int[] next = new int[MAXM];
	static int[] to = new int[MAXM];
	// 构建小根堆
	static PriorityQueue<Integer> heap = new PriorityQueue<>();
	// 入度表
	static int[] indegree = new int[MAXN];
	// 收集拓扑排序结果
	static int[] ans = new int[MAXN];
	static int cnt, heapSize;
	static int n, m;
	public static void build(int n) {
		cnt = 1;
		heap.clear();
		Arrays.fill(head, 0, n + 1, 0);
		Arrays.fill(indegree, 0, n + 1, 0);
	}
	public static void addEdge(int f, int t) {
		next[cnt] = head[f];
		to[cnt] = t;
		head[f] = cnt++;
	}
	public static void main(String[] args) throws IOException {
		n = nextInt();
		m = nextInt();
		build(n);
		for (int i = 0, from, to; i < m; i++) {
			from = nextInt();
			to = nextInt();
			addEdge(from, to);
			indegree[to]++;
		}
		topoSort();
		for (int i = 0; i < n - 1; i++) {
				out.print(ans[i] + " ");
			}

你可能感兴趣的:(算法,bfs,图搜索,图论)