定义:
- 对一个有向无环图( Directed Acyclic Graph 简称DAG ) 进行拓扑排序,是将 中所有顶点排成一个线性序列,使得图中任意一对顶点 和 ,若边 ,则 在线性序列中出现在 之前。
应用:
-
拓扑排序常用来 确定一个依赖关系集中,事物发生的顺序。我们可以把这些事物发生按照依赖关系构成DAG,或者称为 AOV网络(顶点表示活动、边表示活动间先后关系的有向图称做顶点活动网(Activity On Vertex network) )
-
确定一个有向图是否为DAG(即是否有环),若 无法形成拓扑序,则说明有环。(即AOV网络关系中出现矛盾/死循环)
注意! 拓扑序并不唯一,有些活动先后关系可以互换,并不影响。
Kahn算法实现:
对于 个结点 条边 的 有向图 ,Kahn算法基于各点入度进行拓扑排序,时间复杂度
大致过程:
- 预处理得到所有点的入度;
- 找到入度为 的点 ,加入拓扑序,同时删除以 为起点的边(即令相邻的 入度 );
- 重复过程 ,直至无入度为 的点;
- 若还有点未排序,则说明有环;否则说明拓扑排序成功,且该图为DAG。
具体实现:
int num[maxn]; //num[i]表示点 i的拓扑序为 num[i]
bool topo() //对 n个点 m条边(u->v)的有向图进行拓扑排序
{
queue<int> q; //队列存储入度为0的点
int in[maxn]={0},tot=0;
for(int i=1;i<=m;i++) //预处理得到入度
{
int v=e[i].v;
in[v]++;
}
for(int i=1;i<=n;i++) //找到初始入度为0的店
{
if(in[i]==0)
q.push(i);
}
while(!q.empty())
{
int u=q.front();
q.pop();
num[u]=++tot; //加入拓扑序
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].v;
in[v]--;
if(in[v]==0)
q.push(v);
}
}
if(tot==n)
return true;
else //若tot不等于n,说明有环
return false;
}