AOE 网络计算工程完成的关键路径

说明: AOE 网络是有向无环加权图,其中顶点表示事件,弧表示活动,权表示活动持续的时间,通常可以用来估算工程完成的时间,即图中从开始点到结束点之间最长的路径对应的时间。请完成一个程序,完成下列任务:

1 、计算 AOE 网络对应的拓扑排序。如果排序结果不唯一,请输出按照从小到大的顺序排列的结果。从小到大的顺序就是输入的节点序列顺序(参见下面关于输入格式的说明)。如图1中满足要求的拓扑排序是: a-b-c-d-e-f-g-h-k ,图2中满足要求的拓扑排序是:v1-v3-v5-v2-v6-v4-v7-v8-v9

2 、计算 AOE 网络的关键路径。注意关键路径可能不唯一,要求输出所有的关键路径。同样,按照是按照从小到大的顺序输出。例,如果得到两条关键路径,分别是0-1-3-6-8-9和0-1-3-4-5-8-9,那么先输出后一条路径,因为两条路径中前三个节点相同,而后一条路径第四个节点的编号小。

测试用例的输入输出格式说明:

输入:

节点的个数,边的条数;

各个节点的名称序列

边: < 起点 , 终点 , 权值 > 。说明起点和终点是在各个点在输入序列中的位置,如图1中边 <a,b> 表示为 <0,1,6> 。

输出:

拓扑排序;

关键路径

测试用例0是与图1相对应的,测试用例1是与图2相对应的。

 测试输入关于“测试输入”的帮助期待的输出关于“期待的输出”的帮助时间限制关于“时间限制”的帮助内存限制关于“内存限制”的帮助额外进程关于“{$a} 个额外进程”的帮助
测试用例 1以文本方式显示
  1. 9,11↵
  2. a,b,c,d,e,f,g,h,k↵
  3. <0,1,6>,<0,2,4>,<0,3,5>,<1,4,1>,<2,4,1>,<4,6,8>,<4,7,7>,<3,5,2>,<5,7,4>,<6,8,2>,<7,8,4>↵
以文本方式显示
  1. a-b-c-d-e-f-g-h-k↵
  2. a-b-e-h-k↵
1秒64M0
测试用例 2以文本方式显示
  1. 9,11↵
  2. v1,v2,v3,v4,v5,v6,v7,v8,v9↵
  3. <0,4,6>,<0,2,4>,<0,5,5>,<4,1,1>,<2,1,1>,<1,6,8>,<1,7,7>,<5,3,2>,<3,7,4>,<6,8,2>,<7,8,4>↵
以文本方式显示
  1. v1-v3-v5-v2-v6-v4-v7-v8-v9↵
  2. v1-v5-v2-v8-v9↵
1秒64M0
测试用例 3以文本方式显示
  1. 4,4↵
  2. A,B,C,D↵
  3. <0,1,2>,<1,3,3>,<3,2,5>,<2,1,1>↵
以文本方式显示
  1. NO TOPOLOGICAL PATH↵
1秒64M0

 

#include<stdio.h>  
#include<string.h>  
#include<stdlib.h>  
  
int vnum, arcnum;  
int topo[55], path[100];  
  
struct link  
{  
    int dir;//目标位置  
    int weight;//权值  
};  
struct vex  
{  
    char name[5];  
    int inNum = 0; //入度  
    int outNum = 0; //出度  
    int ve, vl;   //事件的最早和最晚发生时间   
    link linkTo[300];  
    int linkNum = 0;  
};  
  
vex node[50];  
  
  
int comp(const void*a,const void*b)  
{  
    return *(int*)a-*(int*)b; //从小到大   
}   
  
int comp2(const void*a,const void*b)  
{  
    return *(int*)b-*(int*)a; //从大到小   
}   
  
  
/*把顶点和边信息读入到表示图的邻接表中*/  
void CreateGraph()  
{  
    char str[500] = { '\0' };  
    scanf("%s",str);  
    int len = strlen(str), q = 0, k = 0;  
    for (int i = 0; i < len; i++)  
    {  
        if (str[i] != ',')  
            node[k].name[q++] = str[i];  
        else  
        {  
            node[k].name[q] = '\0';  
            k++;  
            q = 0;  
        }  
    }  
    getchar();  
      
    int a,b,c;  
    for(int i=0;i<arcnum;++i) //建立邻接链表   
    {  
        scanf("<%d,%d,%d>",&a,&b,&c);  
        node[b].inNum++;  
        node[a].outNum++;  
        node[a].linkTo[node[a].linkNum].dir=b;  
        node[a].linkTo[node[a].linkNum].weight=c;  
        node[a].linkNum++;  
        getchar();    
    }  
      
    for (int i = 0; i < vnum; i++) //对邻节点排序  
        qsort(node[i].linkTo, node[i].linkNum, sizeof(node[i].linkTo[0]), comp); //linkNum   
}  
  
/*广度优先搜索获取拓扑序列 */  
int TopoLogicalSort_DFS()  
{  
    int *Stack, u, v, top = 0, count = 0;  
    Stack = (int*)malloc(sizeof(int) * vnum);   
    for (int i = 0; i < vnum; i++)//将度为0的顶点入栈   
    {  
        node[i].ve = 0;   
        if (node[i].inNum == 0) Stack[top++] = i;  
    }  
    while (top > 0)  
    {  
        u = Stack[--top]; //取栈顶   
        topo[count++] = u;  
  
        for (int i = 0; i <= node[u].linkNum; i++)//将u的邻接点入度减1,并将入度为0的顶点入栈   
        {  
            int v = node[u].linkTo[i].dir;  
            if (node[v].ve < node[u].ve + node[u].linkTo[i].weight)  node[v].ve = node[u].ve + node[u].linkTo[i].weight;  
            if (--node[v].inNum == 0)   Stack[top++] = v;  
        }  
        qsort(Stack, top, sizeof(Stack[0]), comp2);//从大到小入栈  
    }  
    free(Stack);  
    return (count == vnum) ? 1 : 0;   
}  
  
/*路径输出*/  
void PrintPath(int top, int end)  
{  
    int u = path[top - 1];  
    if (u == end)  
    {  
        printf("%s", node[path[0]].name); //输出关键路径   
        for (int i = 1; i < top; i++)  
            printf("-%s", node[path[i]].name);  
        printf("\n");  
        return;  
    }  
    for (int i = 0; i <= node[u].linkNum; i++)  
    {  
        int v = node[u].linkTo[i].dir;  
        if (node[u].ve + node[u].linkTo[i].weight < node[v].ve)  continue;  
        if (node[v].ve == node[v].vl)//关键事件  
        {  
            path[top++] = node[u].linkTo[i].dir;//入栈  
            PrintPath(top, end); //递归   
            top--;//退栈  
        }  
    }  
}  
  
/*求关键路径*/  
void CriticalPath()  
{  
    if (!TopoLogicalSort_DFS())  
    {  
        printf("NO TOPOLOGICAL PATH\n");  
        return;  
    }  
    for (int i = 0; i < vnum; i++)  
    {  
        node[i].vl = node[vnum - 1].ve; //初始化各事件最晚发生事件为最后一个事件发生的时间   
        if (i)  printf("-");  
        printf("%s", node[topo[i]].name); //打印拓扑序列  
    }  
    printf("\n");  
    for (int i = vnum - 2; i >= 0; i--)  
    {  
        int u = topo[i];  
        for (int j = 0; j <= node[u].linkNum; j++)  
        {  
            int v = node[u].linkTo[j].dir;  
            if (node[u].vl > node[v].vl - node[u].linkTo[j].weight)  node[u].vl = node[v].vl - node[u].linkTo[j].weight;  
        }  
    }  
    path[0] = topo[0];  
    PrintPath(1, topo[vnum - 1]);  
}  
  
int main()  
{  
    scanf("%d,%d", &vnum, &arcnum);  
    CreateGraph();//把顶点和边信息读入到表示图的邻接表中   
    CriticalPath();//求关键路径  
    return 0;  
}  

 

  • 3
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值