拓扑排序
拓扑排序简介
有序无环图有拓扑排序,拓扑排序是一个有向无环图的所有顶点的线性序列必须满足两个条件:
- 每个顶点出钱且只出现一次
- 若存在一条从顶点A到顶点B的路径,那么在序列中顶点A出现在顶点B前面
有向无环图才有拓扑排序,非DAG没有拓扑排序
如何得到拓扑排序
- 从DAG图中选择一个没有前驱(入度为0)的顶点并输出
- 从图中删除该顶点和所有以他为起点的有向边
- 重复1,2,知道当前的DAG图为空或当前图中不存在无前驱的顶点为止。后一种情况说明有向图中必然存在环。
一个有向无环图可以有一个或多个拓扑排序
拓扑排序的实现
AcWing 848 有向图的拓扑序列
import java.util.*;
class Graph{
//稠密图用临界矩阵存储,稀疏图用临界表存储
public final int N = 100010;
public int[] ne = new int[N];
public int[] e = new int[N];
public int[] h = new int[N];
//用于存储入度
public int[] v = new int[N];
public int[] isu = new int[N];
//数组实现队列
public int[] q = new int[N];
public int idx = 0,t = 0,he = 0;
public Graph(){
Arrays.fill(ne,-1);
Arrays.fill(h,-1);
}
public void add(int a, int b){
v[b]++;
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
public boolean topo(int n){
int begin = 0;
for(int i = 1; i <= n; i++){
if(v[i] == 0){
q[++he] = i;
}
}
while(t!=he){
int te = q[++t];
for(int i = h[te]; i != -1; i=ne[i]){
v[e[i]]--;
if(v[e[i]] == 0){
q[++he] = e[i];
}
}
}
if(n == t){
for(int i = 1; i <= n; i++) System.out.print(q[i]+" ");
return true;
}else{
System.out.print(-1);
return false;
}
}
}
public class Main{
public static void main(String[] args){
Scanner Reader = new Scanner(System.in);
Graph gra = new Graph();
int n = Reader.nextInt(),m = Reader.nextInt();
while(m--!= 0){
gra.add(Reader.nextInt(),Reader.nextInt());
}
gra.topo(n);
}
}