一、什么是拓扑排序在图论中,拓扑排序(Topological Sorting)是一个有向无环图(DAG, Directed Acyclic Graph)的所有顶点的线性序列。且该序列必须满足下面两个条件:
每个顶点出现且只出现一次。若存在一条从顶点 A 到顶点 B 的路径,那么在序列中顶点 A 出现在顶点 B 的前面。有向无环图(DAG)才有拓扑排序,非DAG图没有拓扑排序一说。
例如,下面这个图:
它是一个 DAG 图,那么如何写出它的拓扑排序呢?这里说一种比较常用的方法:
1:从 DAG 图中选择一个 没有前驱(即入度为0)的顶点并输出。 2:从图中删除该顶点和所有以它为起点的有向边。 3:重复 1 和 2 直到当前的 DAG 图为空或当前图中不存在无前驱的顶点为止。后一种情况说明有向图中必然存在环。
于是,得到拓扑排序后的结果是 { 1, 2, 4, 3, 5 }。
通常,一个有向无环图可以有一个或多个拓扑排序序列。
二、拓扑排序的应用拓扑排序通常用来“排序”具有依赖关系的任务。
比如,如果用一个DAG图来表示一个工程,其中每个顶点表示工程中的一个任务,用有向边表示在做任务 B 之前必须先完成任务 A。故在这个工程中,任意两个任务要么具有确定的先后关系,要么是没有关系,绝对不存在互相矛盾的关系(即环路)。
三 题目:
给定一个n个点m条边的有向图,图中可能存在重边和自环。
请输出任意一个该有向图的拓扑序列,如果拓扑序列不存在,则输出-1。
若一个由图中所有点构成的序列A满足:对于图中的每条边(x, y),x在A中都出现在y之前,则称A是该图的一个拓扑序列。
输入格式
第一行包含两个整数n和m
接下来m行,每行包含两个整数x和y,表示存在一条从点x到点y的有向边(x, y)。
输出格式
共一行,如果存在拓扑序列,则输出拓扑序列。
否则输出-1。
数据范围
1≤n,m≤1051≤n,m≤105
输入样例:
3 3
1 2
2 3
1 3
输出样例:
1 2 3
############################################
1 #include
2 using namespace std;
3
4 const int N = 1e5+10;
5 vector
6 int idx;
7 int q[N],hh = 0, tt = -1;//模拟队列
8 int d[N];//入度
9 int n, m;
10
11 void add(int a, int b){
12 e[idx] = b;
13 ne[idx] = h[a];
14 h[a] = idx ++;
15 }
16
17 bool topsort(){
18 for(int i = 1;i <= n;++i)
19 if(d[i] == 0) q[++tt] = i;
20 while(hh <= tt){
21 int t = q[hh++];
22 for(int i = h[t];i != -1;i = ne[i]){
23 int tmp = e[i];
24 -- d[tmp];
25 if(d[tmp] == 0) q[++tt] = tmp;
26 }
27 }
28 return tt == n-1;
29 }
30
31 int main(){
32 cin >> n >> m;
33 for(int i = 0;i < m;++i){
34 int a, b;
35 cin >> a >> b;
36 add(a, b);
37 d[b] ++;
38 }
39 if(topsort()){
40 for(int i = 0;i < n;++i)cout << q[i] << " ";
41 }else cout << -1 << endl;
42 return 0;
43 }
View Code