【正确答案】(1)数据结构
typedef int Vexfype;
typedef int AdjType;
typedef struct{
VexType vexs[MAXVEX]; /*顶点信息*/
adjType arcs[MAXVEX][MAXVEX]; /*边信息*/
int n; /*图的顶点个数*/
}GraphMatrix;
typedef struct{
VexType vexs[MAXVEX]; /*顶点信息*/
int vexsno[MAXVEX]; /*顶点在顶点表中的下标值*/
}Topo;
(2)思路
按照邻接矩阵表示法创建出邻接矩阵,矩阵中第i行第j列存储由顶点i到顶点j的活动的权值aij,若不存在相应边,则aij=0。先用拓扑排序法确定AOE网的一个拓扑序列,再根据确定好的序列分别计算出各个顶点的最早可能发生时间、最迟允许发生时间和各个活动的最早开始时间、最迟开始时间。通过判断活动的最早开始时间和最迟开始时间,可以确定AOE网的关键路径。
(3)算法
void findlnDegree(GraphMatrix*paoe,int*inDegree){
/*求出图中所有顶点的入度,方法是搜索整个邻接表*/
inti,j;
for(i=0;i<paoe->n;i++)
inDegree[i]=O;
for(i=0;i<paoe->n;i++)
for(j=0;j<paoe->n;j++)
if(j!=i&&paoe->arcs[j][i]!=MAX)++inDegree[i];
}
int topoSort(GraphMatrix*paoe,Topo*ptopo){
int i,j,k,nodeno=0,top=-1;
int indegree[MAXVEX];
findInDegree(paoe,indegree);
for(i=0;i<paoe->n;i++)
if(indegree[i]==0){ /*将入度为零的顶点入栈*/
indegree[i]=top;
top=i;
}
while(top!=-1){ /*栈不为空*/
j=top;
top=indegree[top]; /*取出当前栈硕元素*/
ptopo->vexs[nodeno]=paoe->vexs[j];/*将该元素输出到拓扑序列中*/
ptopo->Vexsno[nodeno++]=j;
for(i=0;i<paoe->n;i++){ /*删除以该顶点为起点的边*/
if(i!=j&&paoe->arcs[j][i]!=MAX){
k=i;
indegree[k]--;
if(indegree[k]==0){ /*将新的入度为零的边入栈*/
indegree[k]=top;
top=k;
}
}
}
}
if(nodeno<paoe->n){ /*AOV网中存在回路*/
printf("The aov network has a cycle\n");
return FALSE;
}
return TRUE;
}
int CriticalPath(GraphMatrix*paoe){
int i,j,k;
AdjType ee[MAXVEX],le[MAXVEX],1[MAXEDGE],e[MAXEDGE];
Topotopo;
if(topoSort(paoe,&topo)==FALSE) /*求AOE网的一个拓扑序列*/
return FALSE;
for(i=0;i<paoe->n;i++)
ee[i]=0;
for(k=0;k<paoe->n;k++){
/*求事件vj可能的最早发生时间ee(j)*/
i=topo.vexsno[k];
for(j=0;j<paoe->n;j++)
if(j!=i&&paoe->arcs[i][j]<MAX&&ee[i]+paoe->arcs[i][j]>ee[j]])
ee [j]=ee[i]+paoe->arcs[i][j];
}
for(i=0;i<paoe->n;i++) /*求事件vi允许的最迟发生时间le(i)*/
le[i]=ee[paoe->n-1];
for(k=paoe->n-2;k>=0;k--){
i=topo.vexsno[k];
for(j=0;j<paoe->n;j++)
if(j!=i&&paoe->arcs[i][j]<MAX&&le[j]-paoe->arcs[i][j]<le[i])
le[i]=le[j]-paoe->arcs[i][j];
}
k=0:
printf("k<start,end>weight e(k)l(k) state\n");
for(i=0;i<paoe->n;i++)
/*求活动ak的最早开始时间e(k)及最晚开始时间l(k)*/
for(j=0;j<paoe->n;j++)
if(j!=i&&paoe->arcs[i][j]<MAX){
e[k]=ee[i];
l[k]=le[j]-paoe->arcs[i][j];
printf("/%2d<v/%d,v/%d>/%6d/%4d/%4d",k,i,j,
paoe->arcs[i][j],e[k],l[k]);
if(e[k]==l[k])
printf("Critical");
printf("\n");
k++:
}
printf("\n");
printf("Minimum project time cost:/%d\n",le[paoe->n-1]);
return TRUE;
}
(4)代价分析
1)拓扑排序算法
算法首先检查入度为0的顶点,并将这些顶点压入栈,花费的时间为O(n2)。然后,在进行拓扑排序时,每个顶点都入栈一次,且邻接矩阵中每个元素都被检查一遍,运行时间为O(n2)。因此,拓扑排序算法的时间复杂度为O(n2)。
2)求关键路径算法
在求事件可能的最早发生时间及允许的最迟发生时间,以及活动的最早开始时间和最晚开始时间时,都要对图邻接矩阵中每个元素检查一遍,时间花费为O(n2)。因此,求关键路径算法的时间代价为O(n2)。
总的时间代价为O(n2)。
【答案解析】该调试结果与采用邻接表表示法时的调试结果完全相同。
调试结果中列出了各活动的可能的最早开始时间和最晚开始时间。
从调试结果中可以看出:
·整个工程的最短完成时间是24。
·活动<V0,V2>,<V2,V3>,<V3,V6>,<V6,V8>,<V8,V9>是关键活动。
·活动<V0,V2>,<V2,V3>,<V3,V6>,<V6,V8>,<V8,V9>提高速度后能导致整个工程提前完成。