一、拓扑排序
由AOV网构造拓扑序列的拓扑排序算法主要是循环执行以下两步,直到不存在入度为0的顶点为止。
- 选择一个入度为0的顶点并输出之。
- 从网中删除此顶点及所有出边。
循环结束后,若输出的顶点数小于网中的顶点数,则输出“有回路”信息,否则输出的顶点序列就是一种拓扑序列。
#define MAXVEX 100
using namespace std;
typedef struct edge_node //边表节点
{
int adjvex;//邻接点域
int weight;//权值
struct edge_node* next;
}edge_node;
typedef struct vertex_node //顶点表节点
{
int in;//入度
int data;//顶点信息
edge_node* first_edge;
}vertex_node,AdjList[MAXVEX];
typedef struct
{
AdjList adjlist;
int num_vertexes, num_edges;
}graphadjlist;
bool TopologicalSort(graphadjlist* G)
{
edge_node* e;
int top = 0;//栈下标
int count = 0;//记数输出顶点个数
int stack[MAXVEX];//建栈储存入度0的点
int get_top;//出栈元素
for (int i = 0; i < G->num_vertexes; i++)
{
if (G->adjlist[i].in == 0)
stack[++top] = i;
}
while (top != 0)
{
get_top = stack[top--];
cout << G->adjlist[get_top].data;//打印顶点
count++;
int k;
for (e = G->adjlist[get_top].first_edge;; e = e->next)
{
k = e->adjvex;
G->adjlist[k].in--;//该点邻接点域入度减一
if (G->adjlist[k].in == 0)
stack[++top] = k;
}
}
if (count < G->num_vertexes)//小于顶点数,存在环
return false;
else
return true;
}
二、关键路径
只有在某顶点所代表的事件发生后,从该顶点出发的各有向边所代表的活动才能开始。只有在进入某一顶点的各有向边所代表的活动都已经结束,该顶点所代表的事件才能发生。表示实际工程计划的AOE网应该是无环的,并且存在唯一的入度为0的开始顶点和唯一的出度为0的完成顶点。
当网中关键路径不唯一时,只有加快的关键活动或关键活动组合包括在所有的关键路径上才能缩短工期。
int etv[MAXVEX];//事件最早发生数组
int ltv[MAXVEX];//事件最迟发生数组
int stack2[MAXVEX];
int top2 = 0;//操作栈2
bool TopologicalSort(graphadjlist* G)
{
edge_node* e;
int top = 0;//栈下标
int count = 0;//记数输出顶点个数
int stack[MAXVEX];//建栈储存入度0的点
int get_top;//出栈元素
for (int i = 0; i < G->num_vertexes; i++)
{
if (G->adjlist[i].in == 0)
stack[++top] = i;
}
for (int i = 0; i < G->num_vertexes; i++)
etv[i] = 0;
while (top != 0)
{
get_top = stack[top--];
cout << G->adjlist[get_top].data;//打印顶点
stack2[++top2] = get_top;
count++;
int k;
for (e = G->adjlist[get_top].first_edge;; e = e->next)
{
k = e->adjvex;
G->adjlist[k].in--;//该点邻接点域入度减一
if (G->adjlist[k].in == 0)
stack[++top] = k;
if (etv[get_top ] + e->weight > etv[k])
//求各顶点最早发生时间
etv[k] = etv[get_top] + e->weight;//更新后面
}
}
if (count < G->num_vertexes)//小于顶点数,存在环
return false;
else
return true;
}
//求关键路径
void CriticalPath(graphadjlist* G)
{
edge_node* e;
int ete, lte;//活动最早和最迟发生时间
int get_top,k;
TopologicalSort(G);
for (int i = 0; i < G->num_vertexes; i++)
{
ltv[i] = etv[G->num_vertexes - 1];//初始化事件的最迟发生时间
}
while (top2)
{
get_top = stack2[top2--];//将拓扑排序出栈
for (e = G->adjlist[get_top].first_edge;; e = e->next)
{
k = e->adjvex;
if (ltv[k] - e->weight > ltv[get_top])
etv[get_top] = ltv[k] - e->weight;//倒退更新前面
}
}
for (int j = 0; j < G->num_vertexes; j++)
{
for (e = G->adjlist[j].first_edge;; e = e->next)
{
k = e->adjvex;
lte = ltv[k] - e->weight;//最迟为事件最迟时减去活动时间
ete = etv[k];//最早为事件开始
if (lte == ete)
printf("<V %d ,V %d>,权值%d", G->adjlist[j].data, G->adjlist[k].data, e->weight);
}
}
}