第七章 图(拓扑排序与关键路径)

拓扑排序

拓扑排序是将有向无环图的每个顶点排成一个线性序列。
经典的例子就是AOV网大学四年课程规划的例子。
AOV网
在现代化管理中,人们常用有向图来描述和分析一项工程的计划和实施过程,一个工程常被分为多个小的子工程,这些子工程被称为活动(Activity),在有向图中若以顶点表示活动,有向边表示活动之间的先后关系,这样的图简称为AOV网。

以计算机软件工程专业为例,把该专业的大学四年课程放在一个图中。这些课之间有的有先后关系,有的没有先后关系。比如C语言和高等数学没有先后关系,而离散数学必须在数据结构之前,等等。其实,软件工程专业的四年的所有课程就形成了一个无环有向图。对这个无环有向图进行拓扑排序,形成一个线性序列,然后根据每学期排课的门数,把这个线性序列截成6段,这些课程 就分成了6个学期的课程。这就是拓扑排序!

算法步骤:
1.从 DAG 图中选择一个 没有前驱(即入度为0)的顶点并输出。
2.从图中删除该顶点和所有以它为起点的有向边。
3.重复 1 和 2 直到当前的 DAG 图为空。(如果最后不为空,即存在无前驱的顶点,则说明该图是有环图)

这是拓扑排序的一个实例(对于一个图,拓扑排序后的结果不一定唯一)

第七章 图(拓扑排序与关键路径)_第1张图片
下面程序的输入输出样例是基于上面的这个图进行的。

#include
#include
using namespace std;

const int maxn=1000;

int indegree[maxn];
int mp[maxn][maxn];

string str="0abcdefgh";

void topology_sort(int mp[maxn][maxn],int indegree[maxn],int n){
    //最多搞n次,如果n次后输出的结点个数小于n,则存在环,本程序假设无环
    for(int i=1;i<=n;i++){
        //对入度为0的点进行操作
        for(int j=1;j<=n;j++){
            if(indegree[j]==0){
                cout<" ";
                indegree[j]--;
                //删除与该结点为起点的边
                for(int k=1;k<=n;k++){
                    if(mp[j][k]==1) indegree[k]--;
                }
                break;
            }
        }
    }
    cout<int main()
{
    memset(indegree,0,sizeof(indegree));
    cout<<"输入一个图的邻接矩阵: "<for(int i=1;i<=8;i++)
        for(int j=1;j<=8;j++){
            cin>>mp[i][j];
            if(mp[i][j]==1) indegree[j]++;
        }
    cout<<"拓扑排序的一个结果: ";
    topology_sort(mp,indegree,8);
    return 0;
}

/*
输入输出样例:

输入一个图的邻接矩阵:
0 0 1 0 0 0 1 0
0 0 0 0 0 0 1 1
0 0 0 1 0 0 0 0
0 0 0 0 1 0 1 0
0 0 0 0 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 1 0 0
拓扑排序的一个结果: a b c d g h f e
*/

关键路径

AOE网
AOE网:Activity on edge network
若在带权的有向图中,以顶点表示事件,以有向边表示活动,边上的权值表示活动的开销(如该活动持续的时间),则此带权的有向图称为AOE网。

AOE网具有以下两个性质:
①只有在某顶点所代表的事件发生后,从该顶点出发的各有向边所代表的活动才能开始。
②只有在进入一某顶点的各有向边所代表的活动都已经结束,该顶点所代表的事件才能发生。

AOE网中的关键路径,就是完成整个网络所需的最短时间,亦最长路径。

你可能感兴趣的:(数据结构(基础知识))