1、举例说明:计算机专业排课
说明:学C1,C2是不需要提前学别的课程的,学C3则需要提前学C1,C2。
把课程列表转换为图,其中顶点代表课程,则从V到W有一条边代表:V是W的预修课程
2、拓扑排序
-
拓扑序
:如果图中从V到W有一条有向路径,则V一定排在W之前。满足此条件的顶点序列称为一个拓扑序 - 获得一个拓扑序的过程就是
拓扑排序
- AOV如果有
合理的
拓扑序,则必定是有向无环图
(Directed Acyclic Graph, DAG)
3、算法
void TopSort()
{
for (cnt = 0; cnt < |V| ; cnt++)
{
V = 未输出的入度为0的顶点;// O(|V|)
if (这样的V不存在)//外循环没结束已经找不到入度为0的顶点了,有环
{
Error(“图中有回路”);
break;
}
输出V,或者记录V的输出序号;
for (V 的每个邻接点W)
Indegree[W]––;//相当于去掉从V到W的边
}
}
在TopSort函数中,如果外循环还没结束,就已经找不到“未输出的入度为0的顶点”,则说明图中必定存在回路。
时间复杂度:T = O( |V|2 )
4、聪明的算法
随时将入度变为0的顶点放到一个容器里
void TopSort()
{
for (图中每个顶点V)
if (Indegree[V] == 0)
Enqueue(V, Q);
while (!IsEmpty(Q))
{
V = Dequeue(Q);
输出V,或者记录V的输出序号; cnt++;//计数器增加
for (V 的每个邻接点W)//将V放入容器,V发出的边断开,V的邻接点入度减1
if (––Indegree[W] == 0)
Enqueue(W, Q);
}
if (cnt != |V| )
Error(“图中有回路”);
}
随时将入度为0的节点放入容器中,每次从容器中取出元素,保证都是入度为0。
时间复杂度:每个点被访问一遍,每条边访问一遍
T = O( |V| + |E| )
此算法可以用来检测有向图是否DAG(有向无环图Directed Acyclic Graph)
5、关键路径问题
-
AOE (Activity On Edge)
网络
一般用于安排项目的工序
每条边代表一个工序或者一个活动
边表示活动,顶点表示到达这个顶点时,活动结束了。
顶点的上面部分表示这项工作最早在什么时间完成,下面的表示这项工作最晚什么时间开始。
机动时间:不用那么赶工期,以顶点0到顶点2为例,最早第0天开始工作,最晚第六天完成,而完成这项工作只需要4天时间,就有2天的机动时间。
关键路径:由绝对不允许延误
的活动组成的路径