求如下有向图的关键路径以及任意两点之间的最短距离?

   更新日期:2024.05.02

用CPM算法求有向图的关键路径和用Dijkstra算法求有向图的最短路径的C语言程序如下

#include <stdio.h>

#include <malloc.h>

#include <stdlib.h>

#include <string.h>

#define MAX 20

#define INF 32767      // 此处修改最大值

#define nLENGTH(a)  (sizeof(a)/sizeof(a[0]))

#define eLENGTH(a) (sizeof(a)/sizeof(char))/(sizeof(a[0])/sizeof(char))

typedef struct _graph{

 char vexs[MAX];       // 顶点集合

 int vexnum;           // 顶点数

 int edgnum;           // 边数

 int matrix[MAX][MAX]; // 邻接矩阵

}Graph, *PGraph;

// 边的结构体 

typedef struct _EdgeData{

 char start; // 边的起点

 char end;   // 边的终点

 int weight; // 边的权重

}EData;

//指向节点的位置

int point_node(PGraph g,char c){

 for(int i=0;i<g->vexnum;i++){

  if(g->vexs[i]==c){

   return i;

  }

 }

 return -1;

}

PGraph create_graph(int b[][3],char a[],int n,int e){

 char c1,c2; //边的2个顶点

 PGraph g; //矩阵

 g=(PGraph)malloc(sizeof(Graph));

 //memset()第一个参数 是地址,第二个参数是开辟空间的初始值,第三个参数是开辟空间的大小

 memset(g, 0, sizeof(Graph));

 printf("顶点个数:
");//顶点数

 g->vexnum=n;

 printf("%d
",g->vexnum);

 printf("边个数:
");//边数

 g->edgnum=e;

 printf("%d
",g->edgnum);

 //初始化顶点

 for(int j=0;j<g->vexnum;j++){

  g->vexs[j]=a[j];

 }

 for(int i=0;i<g->edgnum;i++){

  int p1,p2;

  c1=char(b[i][0]);

  c2=char(b[i][1]);

  p1=point_node(g, c1);

  p2=point_node(g, c2);

  if (p1==-1 || p2==-1){

   printf("input error: invalid edge!
");

   free(g);

   continue;

  }

  g->matrix[p1][p2]=b[i][2];

 }

 for(int i=0;i<g->vexnum;i++){

  for(int j=0;j<g->vexnum;j++){

   if(g->matrix[i][j]==0)

    g->matrix[i][j]=INF;

  }

 }

 return g;

}

//关键路径的最短时间

//关键路径法(Critical Path Method,CPM)

void CPM_road(PGraph g){

 int i,j;

 int a[MAX]={0},b[MAX]={-10};

 int max=0;//最长路径

 for( i=0;i<g->vexnum;i++){//列数遍历

  for( j=0;j<g->vexnum;j++){//行数遍历

   //如果g->matrix[j][i]大于0,说明此顶点有前顶点,由前边的遍历可知,前顶点的最长路径a[j],

   //加上g->matrix[j][i]的路径就是当前a[i]的路径

   if(g->matrix[j][i]!=INF && g->matrix[j][i]+a[j]>max){

    max=g->matrix[j][i]+a[j];

    a[i]=max;

   }

  }

  max=0;

 }

 //显示最长路径

 printf("第一个顶点到每一个顶点的最长路径:");

 printf("
");

 for(i=0;i<g->vexnum;i++){

  printf("V%d",i+1);

 }

 printf("
");

 for(i=0;i<g->vexnum;i++){

  printf("%d",a[i]);

 }

 printf("
");

 printf("最后一个顶点到每个顶点的最长路径:");

 for( i=g->vexnum-1;i>=0;i--){ //列数遍历

  for( j=g->vexnum-1;j>=0;j--){ //行数遍历

   //如果g->matrix[j][i]大于0,说明此顶点有前顶点,由前边的遍历可知,前顶点的最长路径a[j],

   //加上g->matrix[j][i]的路径就是当前a[i]的路径

   if(g->matrix[i][j]!=INF && g->matrix[i][j]+b[j]>max){

    max=g->matrix[i][j]+b[j];

    b[i]=max;

   }

  }

  max=0;

 }

  //显示最长路径

 printf("
");

 for(i=0;i<g->vexnum;i++){

  printf("V%d",i+1);

 }

 printf("
");

 for(i=0;i<g->vexnum;i++){

  printf("%d",b[i]);

 }

 printf("
");

 printf("关键路径:
");

 for(i=0;i<g->vexnum;i++){

  if(a[i]==a[g->vexnum-1]-b[i]){

   printf("V%c",g->vexs[i]);

  }

 }

 printf("
");

}

void print_shortest_path(PGraph g,int* distance,int* path,int* used,int start,int end){ 

// 输出最短距离并打印最短路径

 int i = 0, pre, inverse_path[g->vexnum];

 char s1[3],s2[3];

 sprintf(s1, "V%d", (start+1)); 

 sprintf(s2, "V%d", (end+1));

 printf("从%s顶点到%s顶点的最短距离: %d
", s1,  s2, distance[end]);

 inverse_path[i] = end;

 pre = path[end];

 if(pre == -1){

  printf("没有通路!
");

 }else{

  while(pre != start){

   inverse_path[++i] = pre;

   pre = path[pre];

  }

  inverse_path[++i] = start;

  printf("从%s顶点到%s顶点的最短路径:
", s1, s2);

  for(; i > 0; i--){

   sprintf(s1, "V%d", (inverse_path[i]+1));

   printf("%s -> ", s1);

  }

  sprintf(s1, "V%d", (inverse_path[i]+1));

  printf("%s
", s1);

 }

 return;

}

void shortest_path(PGraph g,int start, int end){ // 基于Dijkstra算法的最短路径函数

 int distance[g->vexnum]; // 用于存放起始点到其余各点的最短距离

 int path[g->vexnum]; // 用于存放起始点到其余各点最短路径的前一个顶点

 int used[g->vexnum] = { 0 }; // 用于标记该顶点是否已经找到最短路径

 int i, j, min_node, min_dis, pass_flag = 0;

 for(i = 0; i < g->vexnum; i++){

  distance[i] = g->matrix[start][i]; // 初始化距离数组

  if(g->matrix[start][i] < INF){

   path[i] = start; // 初始化路径数组

  }else{

   path[i] = -1;

  }

 }

 used[start] = 1;

 path[start] = start;

 for(i = 0; i < g->vexnum; i++){

  min_dis = INF;

  for(j = 0; j < g->vexnum; j++){

   if(used[j] == 0 && distance[j] < min_dis){

    min_node = j;

    min_dis = distance[j];

    pass_flag++; // 标记是否存在通路

   }

  }

  if(pass_flag != 0){

   used[min_node] = 1;

   for(j = 0; j < g->vexnum; j++){

    if(used[j] == 0){

     if(g->matrix[min_node][j] < INF && distance[min_node] + g->matrix[min_node][j] < distance[j]){

      distance[j] = distance[min_node] + g->matrix[min_node][j];

      path[j] = min_node;

     }

    }

   }

  }

 }

 print_shortest_path(g,distance, path, used, start, end);

 return;

}

int main(){

 int i,j;

 PGraph gp;

 char a[]={'1', '2', '3', '4', '5', '6', '7'};

 int b[][3]={{'1', '2',3}, 

  {'1', '3',2}, 

  {'1', '4',6}, 

  {'2', '4',2}, 

  {'2', '5',4}, 

  {'3', '4',1}, 

  {'3', '6',3},

  {'4', '5',1},

  {'5', '7',3},

  {'6', '7',4}}; 

  int n=nLENGTH(a);

 int e=eLENGTH(b);

 gp=create_graph(b,a,n,e);

 //打印邻接矩阵

 printf("邻接矩阵:
");

 for (i = 0; i < gp->vexnum; i++){

  for (j = 0; j < gp->vexnum; j++)

   printf("%d  ", gp->matrix[j][i]);

  printf("
");

 }

 CPM_road(gp);

 printf("
");

 for(i=0;i<gp->vexnum;i++){

  for(j=0;j<gp->vexnum;j++){

   if(i!=j)

    shortest_path(gp,i, j);

  }

 }

 return 0;

}


运行结果



  • 13739054470 :求如下有向图的关键路径以及任意两点之间的最短距离?
    奚垂辰1135 :答://如果g->matrix[j][i]大于0,说明此顶点有前顶点,由前边的遍历可知,前顶点的最长路径a[j],//加上g->matrix[j][i]的路径就是当前a[i]的路径 if(g->matrix[j][i]!=INF && g->matrix[j][i]+a[j]>...
  • 13739054470 :数据结构 图之关键路径
    奚垂辰1135 :答:a1 a2 a4 a8 a9 所组成的路径即为关键路径 :a1->a4->a9 和 a2->a8->a9
  • 13739054470 :图的关键路径
    奚垂辰1135 :答:AOV网 :在一个表示工程的有向图中,用顶点表示活动,用弧表示活动之间的优先关系,这样的有向图为顶点表示活动的网,就是AOV网。关键路径算法原理 :先求所有顶点的事件最早发生时间(从起点开始计算),如有顶点1和顶点2...
  • 13739054470 :求AOE网关键路径
    奚垂辰1135 :答:求上图中VOE网中的关键路径:1,求事件的最早开始时间ve=max{顶点+边}和最晚开始时间vl=min{尾-边} 2,为了后面更好的求活动的最早开始时间和最晚开始时间,将ve和vl都在图中标识出来,ve用红笔,vl用黑笔 3,求...
  • 13739054470 :关键路径怎么算
    奚垂辰1135 :答:关键路径的计算方法如下:(1) 输入e条弧<j,k>,建立AOE网的存储结构;(2) 从源点v1出发,令ve(1)=0,求 ve(j) ,2<=j<=n;(3) 从汇点vn出发,令vl(n)=ve(n),求 vl(i), 1<=i<=n-1;(4...
  • 13739054470 :关键路径怎么算
    奚垂辰1135 :答:根据各顶点的ve和vl值,求每条弧s(活动)的最早开始时间e(s)和最晚开始时间l(s),其中e(s)=l(s)的为关键活动。求关键路径必须在拓扑排序的前提下进行,有环图不能求关键路径;只有缩短关键活动的工期才有可能缩短...
  • 13739054470 :求AOE网关键路径
    奚垂辰1135 :答:AOE网是一种用于表示工程的带权有向图,其中顶点代表事件,有向边代表活动,边上的权值表示活动的持续时间。关键路径是指完成整个工程所需的最短时间,这条路径被称为关键路径。关键路径上的活动被称为关键活动,只有缩短...
  • 13739054470 :aoe网完成工程的最短时间
    奚垂辰1135 :答:aoe网完成工程的最短时间是26天。一、在现代化管理中,人们常用有向图来描述和分析一项工程的计划和实施过程,一个工程常被分为多个小的子工程,这些子工程被称为活动(Activity),在带权有向图中若以顶点表示事件,有向...
  • 13739054470 :关键路径怎么求?求详解。
    奚垂辰1135 :答:1.在有向图中选一个没有前驱的顶点且输出。2.从图中删除该顶点和以它为尾的弧。重复上述两步,直至全部顶点均已输出,或者当前图中不存在无前驱的顶点为止。后一种情况则说明有向图中存在环。3.什么是关键路径?例...
  • 13739054470 :已知有向图G的定义如下: G=(V,E) V={a,b,c,d,e} E={, ,,,<c,d>,<e...
    奚垂辰1135 :答:对一个有向无环图G进行拓扑排序,将G中所有顶点排成一个线性序列,使得图中任意一对顶点u和v,若边∈E(G),则u在线性序列中出现在v之前。这样的线性序列称为满足拓扑次序的序列。拓扑排序由某个集合上的一个偏序得到...
  • 相关链接

    欢迎反馈与建议,请联系电邮
    2024 © 视觉网