关键路径的相关知识

来源:互联网 发布:java判断字符串为空格 编辑:程序博客网 时间:2024/06/03 13:15

一 基本概念

   关键路径是对数据结构中图的又一大应用。

1、AOE网的概念:在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,边上的权值表示活动的持续时间,称这样的有向图叫做边表示活动的网,简称AOE网。AOE网中没有入边的顶点称为始点(或源点),没有出边的顶点称为终点(或汇点)。

2、关键路径的概念:从始点到终点的路径长度最大的路径即为关键路径。关键路径上的活动为关键活动。

3、所用到的几个参量定义:

(1)事件Vk的最早发生时间,用ve(k)表示

指从顶点V到Vk的最长路径长度,事件的最早发生时间决定了所有从Vk开始的活动能够开工的最早时间。ve(k)=Max{ve(j)+weight(Vj,Vk)}

(2)事件Vk的最晚发生时间,用vl(k)表示

指在不推迟工期的情况下,保证它指向的事件Vi在ve(i)时刻发生时,该事件最迟发生的时间。vl(j)=Min{(vl(k)-weight(Vj,Vk)}

(3)活动Ak的最早开始时间,用e(i)表示,e(i)=ve(k)

指该活动的起点所表示的最早的开始时间。

(4)活动Ak的最迟开始时间,用l(i)表示,l(i)=vl(j)-weight(Vk,Vj)

指该活动的终点所表示的事件最迟发生时间与该活动所需时间之差。

二 举例

例如:


 

V1

V2

V3

V4

V5

V6

ve(k),事件最早开始时间

0

3

2

6

6

8

vl(k),事件最晚开始时间

0

4

2

6

7

8

上表中V2最晚开始时间有多个,取最小值即可。

 

 

A1

A2

A3

A4

A5

A6

A7

A8

E(i),活动最早开始时间

0

0

3

3

2

2

6

6

 

 

A1

A2

A3

A4

A5

A6

A7

A8

l(i),活动最迟开始时间

1

0

4

4

2

5

6

7

 

E(i)=l(i),即为关键活动。所以关键活动是:A2、A5、A7

下面用C语言来实现:(代码来自:http://luojilie.blog.163.com/blog/static/19182696320117125832393/)

#include <stdio.h>
#include 
<malloc.h>
#define M 20
#define MAX 100

typedef 
struct node
{   
int vex;
    
int length;
    
struct node *next;
}JD;

typedef 
struct tnode
{   
int vexdata;
    
int in;
    
struct node *link;
}TD;

int loc_vertex(TD g[],int vex,int n)  //定位输入结点的存储坐标
{   int i,j;
    
for(i=1;i<=n;i++)
       
if(g[i].vexdata==vex)
       
return(i);
    
return(0);
}

int crt_linklist(TD g[])   //建立邻接链表
{   int n,e,i,j,k,vt,vh,length;
    JD 
*p;
    printf(
"Input and the number of node,arc:");
    scanf(
"%d,%d",&n,&e);

    
for(i=1;i<=n;i++)   //输入结点的信息
    {  printf("g[%d].vexdata=",i);
       scanf(
"%d",&g[i].vexdata);
       g[i].
in=0;
       g[i].link
=NULL;
    }

    
for(k=1;k<=e;k++)   //输入边的信息
    {   printf("Vt,Vh,length:");
    scanf(
"%d,%d,%d",&vt,&vh,&length);
    i
=loc_vertex(g,vt,n);
    j
=loc_vertex(g,vh,n);
    p
=(JD *)malloc(sizeof(JD));
    p
->vex=j;
    p
->length=length;
    p
->next=g[i].link;
    g[i].link
=p;
    }
    
return(n);
}

void cal_in(TD g[],int n)   //计算每个结点的入度
{  int i,k;
   JD 
*p;
   
for(i=1;i<=n;i++)
   {  p
=g[i].link;
      
while(p!=NULL)
      {  k
=p->vex;
     g[k].
in++;
     p
=p->next;
      }
   }
}

int dut(TD g[],int vt,int vh)   //返回每个结点之间的边的权值
{  JD *p;
   p
=g[vt].link;
   
while(p!=NULL)
   {   
if(p->vex==vh)
       
return(p->length);
       
else
      p
=p->next;
   }
   
return(MAX);
}

int toporder(TD g[],int n,int ve[],int top2[],int *t2)    //作用在于求ve[k],和为后面的求vl[k]
{  int top1[M];
   
int m,k,j,top;
   JD 
*p;
   top
=0; m=0;

   
for(j=1;j<=n;j++)  //初始化事件(结点)的最早开始时间,方法二:memset(ve,0,sizeof(ve));
      ve[j]=0;

   
for(j=1;j<=n;j++)
     
if(g[j].in==0)
     {  top1[top]
=j;
    top
++;
     }
   
while(top>0)
   {  j
=top1[--top];

      top2[
*t2]=j;  //t2初值为零
      (*t2)++;

      m
++;
      p
=g[j].link;
      
while(p!=NULL)
      {  k
=p->vex;
     g[k].
in--;
     
if(g[k].in==0)
        top1[top
++]=k;

     
if(ve[j]+dut(g,j,k)>ve[k])   //求ve[k],ve[k]=ve[j]+dut(g,j,k);(ve[1]=0;)
        ve[k]=ve[j]+dut(g,j,k);

     p
=p->next;
      }
   }
   
if(m<n)  return(0);
   
else     return(1);
}

void critical_path(TD g[],int n)
{   
int i,t2=0,j,k,ee,el;
    
char tag;
    JD 
*p;
    
int ve[M],vl[M],top2[M];


    i
=toporder(g,n,ve,top2,&t2);
    
if(!i)
       printf(
"Has a cycle!");

    
else
    {  
for(i=1;i<=n;i++)
      vl[i]
=MAX;

      
///*  求出vl[k]*///
       vl[n]=ve[n];
       
while(t2>0)
       {  j
=top2[--t2];
      p
=g[j].link;
      
while(p!=NULL)
      {  k
=p->vex;
         
if(vl[k]-dut(g,j,k)<vl[j])
          vl[j]
=vl[k]-dut(g,j,k);
         p
=p->next;
      }
       }

    
///*  求出活动的的e[k],l[k]*///
       for(j=1;j<=n;j++)
       {  p
=g[j].link;
      
while(p!=NULL)
      {  k
=p->vex;
         ee
=ve[j];
         el
=vl[k]-dut(g,j,k);
         
if(ee==el)
         tag
='*';//表示关键路径
         else
         tag
=' ';
         printf(
"Vt=%d,Vh=%d,Length=%d,ee=%d,el=%d,%c\n",j,k,dut(g,j,k),ee,el,tag);
         p
=p->next;
      }
       }
    }
}

int  main()
{  
int n;
   TD g[M];
   n
=crt_linklist(g);
   cal_in(g,n);
   critical_path(g,n);
  
return (0);
}