定义:对一个有向无环图(Directed Acyclic Graph简称DAG)G进行拓扑排序,是将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边(u,v)∈E(G),则u在线性序列中出现在v之前。通常,这样的线性序列称为满足拓扑次序(Topological Order)的序列,简称拓扑序列。简单的说,由某个集合上的一个偏序得到该集合上的一个全序,这个操作称之为拓扑排序。
来自https://baike.baidu.com/item/%E6%8B%93%E6%89%91%E6%8E%92%E5%BA%8F/5223807?fr=aladdin
基本思路:
如果一个点只有出度,很明显只能在第一位,同如果一个点只有入度只能放在觉后面。
于是,我们可以先输出无入度的点,然后在这个DAG中就可以忽略这些已经输出的点,接下来就是删掉这些点所连的所有边。再重复此操作,直到图为空(或者没有入度为零的点,此时说明此图不存在拓扑排序)就得到了我们要的序列。
基本实现:
类似于bfs
用一个数组In用来保存入度,先将入度为0的入队,然后一个一个弹出里面的点,进行下列操作
删掉这个点,将其所连的点的入度减一(这里可以看出用邻接表或者链式前向星好一些),当遇到入度为0的将其入队。
最后判断是否有点没有入队,如果有则说明不存在拓扑排序,否则按队列弹出(入队)顺序输出就可以得到一个正确的序列
上面的算法只能求一种拓扑排序,如果要求所有的序列,用dfs按同样的思路进行搜索就行
模板题:http://acm.hdu.edu.cn/showproblem.php?pid=1285
题意很明确
思路:需要求得是字典序最小的一个序列,一般情况下我们是按入队顺序排列,现在我们要小的在前面,很容易想到用优先级队列处理
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include<queue>
#include<set>
#include<vector>
#define maxn 505
using namespace std;
int n, m;
int Que[maxn];
int in[maxn];
vector<vector<int>> Map(maxn);
priority_queue<int, vector<int>, greater<int>> PQ;
void bfs()
{
int End = 1;
for(int i = 1; i <= n; i++)
{
if(!in[i])
{
PQ.push(i);
}
}
while(!PQ.empty())
{
Que[End] = PQ.top();PQ.pop();
int node = Que[End++];
for(auto x : Map[node])
{
in[x]--;
if(!in[x])
{
PQ.push(x);
}
}
}
for(int i = 1; i <= n; i++)
{
printf("%d%c", Que[i], i == n ? '\n' : ' ');
}
}
int main()
{
while(cin >> n >> m)
{
for(int i = 1; i <= n; i++)
{
Map[i].clear();
}
memset(in, 0, sizeof(in));
for(int i = 0; i < m; i++)
{
int u, v;
cin >> u >> v;
Map[u].push_back(v);
in[v]++;
}
bfs();
}
return 0;
}