关键路径的基于P矩阵的算法程序实现,该如何解决

关键路径的基于P矩阵的算法程序实现

    算法步骤:
        (1)构造图G的P邻接矩阵M1(M的一次幂);
        (2)构造M;
        (3)删去M1中除去第一行之外的所有行得到的矩阵仍然记为M1   ;
        (4)构造秩为k的基本P矩阵Mk(M的k次幂)(k=2,…,n-1)且只保留各顶点之间的最长路径项;
        (5)计算W且只保留源点到汇点的最长路径项;
        (6)输出所有关键路径。
      本人学习C++时间不长,对以上算法不是很清楚,不知如何编写程序。希望熟悉这种算法的高手指点,谢谢-。-

------解决方案--------------------
C/C++ code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_VERTEX_NUM 30 //图的最大顶点数
#define MAX 30            //栈的最大容量
#define INFINITY 30000;   //定义最大的最迟发生时间
enum BOOL {False,True};
typedef struct ArcNode
{int adjvex;              //该弧所指向的顶点的位置
 int weight;              //该弧所代表的活动的持续时间
 struct ArcNode *nextarc; //指向下一条弧的指针
}ArcNode;       //弧结点
typedef struct
{int indegree[MAX_VERTEX_NUM]; //存放各顶点的入度
 ArcNode* AdjList[MAX_VERTEX_NUM]; //指向第一条依附该顶点的弧的指针
 int vexnum,arcnum;                //图的当前顶点和弧数
}Graph;
typedef struct    //定义堆栈结构
{int elem[MAX];   //栈区
 int top;         //栈顶指针
}Stack;
int ve[MAX_VERTEX_NUM];  //全局变量,存放各顶点的最早发生时间
void CreateGraph(Graph &);    //生成图的邻接表
BOOL CriticalPath(Graph);     //求图的关键路径
BOOL TopologicalSort(Graph,Stack &T);  //进行拓扑排序
void FindInDegree(Graph&);    //求图各顶点的入度
void Initial(Stack &);     //初始化一个堆栈
BOOL Push(Stack &,int);  //将一个元素入栈
BOOL Pop(Stack&,int &);  //将一个元素出栈
BOOL Gettop(Stack,int&); //得到栈顶元素
BOOL StackEmpty(Stack);  //判断堆栈是否为空
void main()
{Graph G;  //采用邻接表结构的图
 char j='y';
 BOOL temp;
 //------------------程序解说----------------------------
 printf("本程序将演示构造图的关键路径.\n");
 printf("首先输入图的顶点数和弧数.\n格式:顶点数,弧数;例如:6,8\n");
 printf("接着输入各弧(弧尾,弧头)和权值.\n格式:弧尾,弧头,权值;例如:\n1,2,3\n1,3,2\n");
 printf("2,5,3\n5,6,1\n2,4,2\n4,6,2\n3,4,4\n3,6,3\n");
 printf("程序将会构造该图并找出其关键路径.\n");
 printf("关键路径:\n1->3  2\n3->4  4\n4->5  2\n");
 //------------------------------------------------------
 while(j!='N'&&j!='n')
      {CreateGraph(G);          //生成邻接表结构的图
       temp=CriticalPath(G);    //寻找G的关键路径
       if(temp==False) printf("该图有回路!\n");
         //若返回为False,表明该图存在有环路
       else printf("该图没有回路!\n");
       printf("关键路径演示完毕,继续进行吗?(Y/N)");
       scanf(" %c",&j);
     }
}

BOOL CriticalPath(Graph G)
{//G为有向网,输出G的各项关键活动
 int j,dut,k,ee,el;
 int vl[MAX_VERTEX_NUM]; //存放各顶点的最迟发生时间
 Stack T;     //堆栈T存放拓扑排序的顶点序列
 ArcNode*p;
 Initial(T);  //初始化堆栈T
 if(!TopologicalSort(G,T)) return False; 
    //利用拓扑排序求出各顶点的最早发生时间,并用T返回拓扑序列,
    //若返回False,表明该网有回路
 printf("Critical Path:\n");
 Gettop(T,k); //k取得拓扑序列的最后一个顶点,即该网的汇点
 vl[k]=ve[k]; //汇点的vl=ve
 for(j=1;j<=G.vexnum;j++) if(j!=k) vl[j]=INFINITY; //将其他的顶点的vl置为IFINITY
 while(!StackEmpty(T)) //按拓扑逆序求各顶点的vl值
  {Pop(T,j);
   for(p=G.AdjList[j];p;p=p->nextarc)
     {k=p->adjvex;
      dut=p->weight;
      if(vl[k]-dut<vl[j]) vl[j]=vl[k]-dut;  
         //vl的求法:vl(i)=Min{vl(j)-dut(<i,j>)} <i,j>∈S,i=n-2,...0
     }
  }
 for(j=1;j<=G.vexnum;j++)  //求每条弧的最早开始时间ee和最迟开始时间el
   for(p=G.AdjList[j];p;p=p->nextarc)
      {k=p->adjvex;
       dut=p->weight;
       ee=ve[j];
       el=vl[k]-dut;
       if(ee==el) printf("%d->%d%5d\n",j,k,dut); //若ee=el,则该弧为关键活动
      }
 return True;
}
void CreateGraph(Graph &G)
{//构造邻接表结构的图G
 int i;
 int start,end,arcweight;
 ArcNode *s;
 printf("请输入顶点数和弧数(顶点数,弧数):");
 scanf("%d,%d",&G.vexnum,&G.arcnum); //输入图的顶点数和弧数
 for(i=1;i<=G.vexnum;i++) G.AdjList[i]=NULL; //初始化指针数组
 printf("请输入各弧和权值,格式:弧尾,弧头,权值\n");
 for(i=1;i<=G.arcnum;i++)
   {scanf("%d,%d,%d",&start,&end,&arcweight); 
        //输入弧的起点和终点即该弧所代表的活动的持续时间
    s=(ArcNode *)malloc(sizeof(ArcNode)); //生成一个弧结点
    s->nextarc=G.AdjList[start]; //插入到邻接表中
    s->adjvex=end;
    s->weight=arcweight;
    G.AdjList[start]=s;
   }
}

BOOL TopologicalSort(Graph G,Stack &T)
{//有向网G采用邻接表存储结构,求各顶点事件的最早发生时间ve,
 //T为拓扑序列顶点栈,S为零入度顶点栈。
 //若G无回路,则用栈返回G的一个拓扑序列,且函数返回True,否则返回False
 int i,k;
 int count; //计数器
 ArcNode* p;
 Stack S;
 FindInDegree(G); //求出图中各顶点的入度
 Initial(S);      //堆栈初始化,存放入度为零的顶点
 for(i=1;i<=G.vexnum;i++)
  if(!G.indegree[i]) Push(S,i); //入度为零的顶点入栈
 count=0;     //对输出顶点记数
 for(i=1;i<=G.vexnum;i++)
   ve[i]=0;   //ve初始化 
 while(!StackEmpty(S))
  {Pop(S,i);  //i号顶点出S栈并入T栈,count记数
   Push(T,i); 
   count++;
   for(p=G.AdjList[i];p;p=p->nextarc)
     {k=p->adjvex;       //对i号顶点的每个邻接顶点的入度减一
      if(!(--G.indegree[k])) Push(S,k); //若入度为零,入栈
      if((ve[i]+p->weight)>ve[k]) ve[k]=ve[i]+p->weight;
             //修改k号顶点的最迟发生时间
             //ve的求法:ve(j)=Max{ve(i)+dut(<i,j>)} <i,j>∈S,j=1,2,…,n-1
     }
  }
 if(count<G.vexnum) return False; //如输出顶点数少于图中顶点数,则该图有回路
 else return True;
}
void FindInDegree(Graph &G)
{//求出图G的各顶点的入度,存放在G.indegree[1..G.vexnum]中
 int i;
 ArcNode* p;
 for(i=1;i<=G.vexnum;i++)
   G.indegree[i]=0;
 for(i=1;i<=G.vexnum;i++)
    {
     for(p=G.AdjList[i];p;p=p->nextarc)
       G.indegree[p->adjvex]++;  //弧头顶点的入度加一
    }
}
void Initial(Stack &S)
{S.top=-1;   //栈顶指针初始化为-1
}

BOOL Push(Stack &S,int ch)
{//将元素ch入栈,成功返回True,失败返回False
 if(S.top>=MAX-1) return False;//判断是否栈满
 else {S.top++;               //栈顶指针top加一
       S.elem[S.top]=ch;      //入栈
       return True;
      }
}

BOOL Pop(Stack &S,int &ch)
{//将栈顶元素出栈,成功返回True,并用ch返回该元素值,失败返回False
 if(S.top<=-1) return False;//判断是否栈空
 else {S.top--;                                //栈顶指针减一
       ch=S.elem[S.top+1];
       return True;
      }
}
BOOL Gettop(Stack S,int &ch)
{//取得栈顶元素,成功返回True,并用ch返回该元素值,失败返回False
 if(S.top<=-1)
    return False;
 else {ch=S.elem[S.top];//显示栈顶元素
       return True;
      }
}
BOOL StackEmpty(Stack S)
{//判断堆栈是否已空,若空返回True,不空返回False
 if(S.top<=-1) return True;
 else return False;
}