拓扑排序的重要应用就是判断有向无环图。
算法思想:
1、定义一个队列,所有入度为0的顶点加入队列。
2、取队首顶点,输出,然后删除从该顶点出发的所有边,并令这些边到达的顶点的入度-1,如果某个顶点入度减为0,则将其加入队列。
3、重复步骤2,直到队列为空。
注意:如果要求有多个入度为0的顶点时选择编号最小的顶点,那么把queue改成priority_queue()即可,(priority_queue<int, vector<int>, greater<int>> q)
并保持队首元素(堆首元素)是有限序列中最小的元素,或者用set也可以。(set<int> s)
priority_queue<int> q;
priority_queue<int, vector<int>, less<int>> q;
priority_queue<int, vector<int>, greater<int>> q;
第一种方式和第二种方式等价。
priority_queue有三个参数,第一个是数据类型,第二个是来承载底层堆结构的容器,如果第一个参数是char或者double,则第二个参数填写vector<char>
、vector<double>
即可。
第三个参数less<int>
表示数字大的优先级大,greater<int>
表示数字小的优先级大。
#include<bits/stdc++.h>
using namespace std;
const int MAXV = 1100;
vector<int> G[MAXV];
int n, m, inDegree[MAXV];
bool topologicalSort()
{
int num = 0; //记录加入拓扑序列的顶点数
queue<int> q;
for(int i = 0; i < n; i++)
{
if(inDegree[i] == 0)
q.push(i); //将所有入度为0的结点入队
}
while(!q.empty())
{
int u = q.front(); //取队首顶点u
// printf("%d", u); //此处可输出顶点u,作为拓扑排序中的序列
q.pop();
for(int i = 0; i < G[u].size(); i++)
{
int v = G[u][i]; //u的后继结点v
inDegree[v]--; //v入度-1
if(inDegree[v] == 0) //顶点v的入度减为0则入队
q.push(v);
}
G[u].clear(); //清空顶点u的所有出边(如无必要可不写)
num++; //加入拓扑排序的顶点数+1
}
if(num == n) //加入拓扑排序的顶点数为n,说明拓扑排序成功
return true;
else
return false; //加入拓扑排序的顶点数小于n,排序失败
}