拓扑序列
Posted sxq-study
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了拓扑序列相关的知识,希望对你有一定的参考价值。
一、什么是拓扑排序
在图论中,拓扑排序(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图来表示一个工程,其中每个顶点表示工程中的一个任务,用有向边<A,B><A,B>表示在做任务 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 <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 1e5+10; 5 vector<int> h(N,-1), e(N,-1), ne(N,0); 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 }
以上是关于拓扑序列的主要内容,如果未能解决你的问题,请参考以下文章