Diagram of data structure (7) - critical path

In a weighted directed graph representing a project, events are represented by vertices, activities are represented by directed edges, and durations of activities are represented by weights of edge lengths. The edges of such directed graphs represent a network of activities, which we call It is the AOE network (Activity On Edge Network).

We call the vertices with no incoming edges in the AOE network as the origin or source, and the vertices with no outgoing edges as the end or sink. Since a project always has a beginning and an end, under normal circumstances, the AOE network has only one source and one sink. as the picture shows


Since the AOE network represents the engineering process, it has obvious engineering characteristics. Activities starting from a vertex can only start after the time represented by the vertex occurs. The event represented by a vertex can only occur after all the activities that entered it have ended.

Although AOE net and AOV net are both used to model engineering, they are still very different, mainly reflected in the fact that AOV net is a net whose vertices represent activities, it only describes the constraints between activities, while AOE net is a network with edges representing activities, and the weights on the edges represent the duration of the activity.

The sum of the duration of each activity on the path is called the path length, the path with the maximum length from the source point to the sink point is called the critical path, and the activities on the critical path are called key activities.

The principle of critical path algorithm

Find the start time and latest start time of all activities, and compare them. If they are equal, it means that this activity is a critical activity, and the path between activities is a critical path. If it doesn't, it's not.
To do this, we need to define the following parameters:
1. The earliest occurrence time of the event etv (earliest time of vertex): the earliest occurrence time of the vertex vk;
2. The latest occurrence time of the event ltv (lastest time of vertex): that is, the latest occurrence time of the vertex vk, that is, the latest time that the time corresponding to each vertex needs to start, beyond this time will delay the entire construction period.
3. The earliest start time of the activity ete (earliest time of edge): the earliest occurrence time of the arc ak.
4. The latest start time of the activity lte (latest time of edge): that is, the latest occurrence time of the arc ak, that is, the latest start time without delaying the construction period.

We are 1 and 2 to obtain 3 and 4, and then judge whether ak is a key activity based on whether ete[k] is equal to lte[k].

critical path algorithm

The AOE network is converted into an adjacency list structure as shown in the figure:

code show as below:
#include "stdio.h"    
#include "stdlib.h"   
#include "io.h"  
#include "math.h"  
#include "time.h"

#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0

#define MAXEDGE 30
#define MAXVEX 30
#define INFINITY 65535

typedef int Status; /* Status is the type of the function, and its value is the function result status code, such as OK, etc.*/  

int *etv,*ltv; /* Array of earliest occurrence time and latest occurrence time of event, global variable */
int *stack2; /* stack used to store topological sequences */
int top2; /* pointer for stack2 */

/* Adjacency matrix structure */
typedef struct
{
	int vexs[MAXVEX];
	int arc[MAXVEX][MAXVEX];
	int numVertexes, numEdges;
}MGraph;

/* Adjacency list structure ****************** */
typedef struct EdgeNode /* edge table node*/
{
	int adjvex; /* Adjacent point field, store the subscript corresponding to the vertex */
	int weight; /* used to store weights, not needed for non-network graphs*/
	struct EdgeNode *next; /* Chain field, pointing to the next adjacency point */
}EdgeNode;

typedef struct VertexNode /* vertex table node*/
{
	int in; /* vertex in-degree */
	int data; /* vertex field, storing vertex information */
	EdgeNode *firstedge;/* edge header pointer*/
}VertexNode, AdjList[MAXVEX];

typedef struct
{
	AdjList adjList;
	int numVertexes,numEdges; /* Current number of vertices and edges in the graph*/
}graphAdjList,*GraphAdjList;
/* **************************** */


void CreateMGraph(MGraph *G)/* component graph*/
{
	int i, j;
	/* printf("Please enter the number of edges and vertices:"); */
	G->numEdges=13;
	G->numVertexes=10;

	for (i = 0; i < G->numVertexes; i++)/* initialize graph*/
	{
		G->vexs[i]=i;
	}

	for (i = 0; i < G->numVertexes; i++)/* initialize graph*/
	{
		for ( j = 0; j < G->numVertexes; j++)
		{
			if (i==j)
				G->arc[i][j]=0;
			else
				G->arc[i][j]=INFINITY;
		}
	}

	G->arc[0][1]=3;
	G->arc[0][2]=4;
	G->arc[1][3]=5;
	G->arc[1][4]=6;
	G->arc[2][3]=8;
	G->arc[2][5]=7;
	G->arc[3][4]=3;
	G->arc[4][6]=9;
	G->arc[4][7]=4;
	G->arc[5][7]=6;
	G->arc[6][9]=2;
	G->arc[7][8]=5;
	G->arc[8][9]=3;

}

/* Use the adjacency matrix to build an adjacency list */
void CreateALGraph(MGraph G,GraphAdjList *GL)
{
	int i,j;
	EdgeNode *e;

	*GL = (GraphAdjList)malloc(sizeof(graphAdjList));

	(*GL)->numVertexes=G.numVertexes;
	(*GL)->numEdges=G.numEdges;
	for(i= 0;i <G.numVertexes;i++) /* Read in vertex information and create vertex table*/
	{
		(*GL)->adjList[i].in=0;
		(*GL)->adjList[i].data=G.vexs[i];
		(*GL)->adjList[i].firstedge=NULL; /* set the edge list to an empty list*/
	}
	
	for(i=0;i<G.numVertexes;i++) /* create an edge table*/
	{
		for(j=0;j<G.numVertexes;j++)
		{
			if (G.arc[i][j]!=0 && G.arc[i][j]<INFINITY)
			{
				e=(EdgeNode *)malloc(sizeof(EdgeNode));
				e->adjvex=j; /* The adjacency number is j */   
				e->weight=G.arc[i][j];
				e->next=(*GL)->adjList[i].firstedge; /* Assign the node pointer pointed to on the current vertex to e */
				(*GL)->adjList[i].firstedge=e; /* Point the current vertex pointer to e */  
				(*GL)->adjList[j].in++;
				
			}
		}
	}
	
}


/* topological sort */
Status TopologicalSort(GraphAdjList GL)
{ /* If there is no loop in GL, output the topologically sorted sequence and return 1, if there is a loop, return 0. */    
	EdgeNode *e;    
	int i,k,gettop;   
	int top=0; /* for stack pointer subscript */
	int count=0;/* used to count the number of output vertices*/   
	int *stack; /* build a stack and push vertices with in-degree 0 onto the stack */   
	stack=(int *)malloc(GL->numVertexes * sizeof(int) );    
	for(i = 0; i<GL->numVertexes; i++)                
		if(0 == GL->adjList[i].in) /* push vertices with in-degree 0 onto the stack*/           
			stack[++top]=i;    

	top2=0;    
	etv=(int *)malloc(GL->numVertexes * sizeof(int) ); /* The earliest event occurrence time array*/    
	for(i=0; i<GL->numVertexes; i++)        
		etv[i]=0; /* initialization */
	stack2=(int *)malloc(GL->numVertexes * sizeof(int) );/* Initialize topological sequence stack*/

	printf("TopologicalSort:\t");
	while(top!=0)    
	{        
		gettop=stack[top--];        
		printf("%d -> ",GL->adjList[gettop].data);        
		count++; /* output vertex i and count */

		stack2[++top2]=gettop; /* Push the popped vertex number into the topological sequence stack*/

		for(e = GL->adjList[gettop].firstedge; e; e = e->next)        
		{            
			k=e->adjvex;            
			if( !(--GL->adjList[k].in) ) /* Decrease the in-degree of the adjoining point of vertex i by 1, if it is 0 after decrementing 1, put it on the stack*/                
				stack[++top]=k;

			if((etv[gettop] + e->weight)>etv[k]) /* Find the earliest occurrence time etv value of each vertex event*/                
				etv[k] = etv[gettop] + e->weight;
		}    
	}    
	printf("\n");   
	if(count < GL->numVertexes)        
		return ERROR;    
	else       
		return OK;
}

/* Find the critical path, GL is a directed network, and output the key activities of G*/
void CriticalPath(GraphAdjList GL)
{    
	EdgeNode *e;    
	int i,gettop,k,j;    
	int ete,lte; /* declare the earliest occurrence time and latest occurrence time variables of the activity */        
	TopologicalSort(GL); /* Find the topological sequence and calculate the values ​​of the array etv and stack2*/
	ltv=(int *)malloc(GL->numVertexes*sizeof(int));/* The earliest event occurrence time array*/   
	for(i=0; i<GL->numVertexes; i++)        
		ltv[i]=etv[GL->numVertexes-1]; /* initialization*/        
	
	printf("etv:\t");   
	for(i=0; i<GL->numVertexes; i++)        
		printf("%d -> ",etv[i]);    
	printf("\n");

	while(top2!=0) /* popping is to ask for ltv */    
	{        
		gettop=stack2[top2--];        
		for(e = GL->adjList[gettop].firstedge; e; e = e->next) /* Find the latest ltv value of each vertex event*/        
		{            
			k=e->adjvex;            
			if(ltv[k] - e->weight < ltv[gettop])               
				ltv[gettop] = ltv[k] - e->weight;        
		}   
	}    
	
	printf("ltv:\t");   
	for(i=0; i<GL->numVertexes; i++)        
		printf("%d -> ",ltv[i]);    
	printf("\n");

	for(j=0; j<GL->numVertexes; j++) /* find ete,lte and key activities*/        
	{            
		for(e = GL->adjList[j].firstedge; e; e = e->next)            
		{                
			k=e->adjvex;                
			ete = etv[j]; /* Earliest event time */                
			lte = ltv[k] - e->weight; /* latest event time */               
			if(ete == lte) /* both are equal i.e. on the critical path*/                    
				printf("<v%d - v%d> length: %d \n",GL->adjList[j].data,GL->adjList[k].data,e->weight);
		}        
	}
}


int main(void)
{    
	MGraph G;    
	GraphAdjList GL;    
	CreateMGraph(&G);
	CreateALGraph(G,&GL);
	CriticalPath(GL);
	return 0;
}
The time complexity of the algorithm is O(n+e).


Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325713397&siteId=291194637