码迷,mamicode.com
首页 > 其他好文 > 详细

关键路径

时间:2015-06-20 09:16:51      阅读:130      评论:0      收藏:0      [点我收藏+]

标签:数据结构   图论   算法   关键路径   aoe网   

#include <iostream>
#include <iomanip>
#include <stack> 
using namespace std;
#define MAX 100

typedef char VertexType; 

typedef struct ArcNode {
	 int adjvex;    				//邻接点域,存储该弧指向顶点的下标 (终点) 
	 struct ArcNode *next;			//指向下一条弧的指针 
	 int weight;					//权重 
}ArcNode;		//边结构 

typedef struct VertexNode {
	VertexType data;				//数据域 
	ArcNode *firstArc;				//指向第一条依附该顶点的弧的指针 	
}VertexNode,AdjVerList[MAX];

typedef struct {
	AdjVerList vertices;			//顶点集		
	int vexnum,arcnum; 				//图的顶点数和弧数
}ALGraph;		//图结构

int ve[MAX];						//各事件的最早发生时间 

void CreateALGraph(ALGraph *G);
void Display(ALGraph *G);
int CriticalPath(ALGraph *G);


/*
求关键路径的基本步骤:
1.对图中顶点进行拓扑排序,在排序过程中按拓扑系列求出每个事件的最早发生事件ve(i)
2.按逆拓扑序列求出每个事件的最晚发生时间vl(i)
3.求出每个活动i的最早开始时间 e(i)和最晚发生时间l(i)
4.找到e(i)=l(i)的活动,即为关键路径 
*/
int main()
{
	ALGraph G;	
	CreateALGraph(&G);
	CriticalPath(&G);
	return 0;
}

//求顶点位置函数
int LocateVex(ALGraph *G,VertexType v)
{
    int i;
    for(i=0;i<G->vexnum;i++)
    {
        if(G->vertices[i].data == v)
            return i;
    }
    return -1;
}

//有向无环图 
void CreateALGraph(ALGraph *G)
{
    VertexType v1,v2;
    int w;
    ArcNode *Arc;

    cout<<"请输入顶点数和边数:";
    cin>>G->vexnum>>G->arcnum;


    cout<<"请输入各顶点的数据:";     
    for(int i=0;i<G->vexnum;i++){
        cin>>G->vertices[i].data;
        G->vertices[i].firstArc = NULL;     //顶点的边表设为空
    }

    cout<<"请依次输入"<<G->arcnum<<"组边对应的两个顶点以及权值,以空格分割:"<<endl;
    for(int k=0;k<G->arcnum;k++) {
		cin>>v1>>v2>>w;
        int i = LocateVex(G,v1);
        int j = LocateVex(G,v2);  
        Arc = new ArcNode;				//新建边 
        Arc->adjvex = j;
        Arc->weight = w;
        Arc->next = G->vertices[i].firstArc;        
        G->vertices[i].firstArc = Arc;
    }
}


//求各顶点的入度(遍历整个邻接表)
void FindIndegree(ALGraph *G,int indegree[MAX])
{
	int i;
	ArcNode *p;
    //初始化每个顶点的入度为0
	for(i=0;i<G->vexnum;i++)
        indegree[i] = 0; 

    for(i=0;i<G->vexnum;i++)
    {
        p = G->vertices[i].firstArc;
        while(p)
        {        	
            indegree[p->adjvex]++;			//将每一个临接到的点(终点)自增 
            p = p->next;
        }

        //cout<<i<<"元素的入度为:"<<indegree[i]<<endl;
    } 
} 

//拓扑排序 
int TopoSort(ALGraph *G,stack<int> &T)		//T为返回逆拓扑序列的栈 
{
	stack<int> s;							//设置辅助栈(正拓扑序列栈) 
	ArcNode *p;
	int i,k;
	
	int indegree[MAX]; 						//各顶点的入度数组 
	FindIndegree(G,indegree);
	
	for(i=0;i<G->vexnum;i++)
	{
		//将入度为0的顶点入栈
		if(indegree[i]==0)
			s.push(i); 
	}
	
	for(i=0;i<G->vexnum;i++) 
		ve[i] = 0;							//初始化最早发生时间 
	
	int count = 0;
	while(!s.empty())
	{
		i = s.top();
		s.pop();							//将栈顶从S栈出栈
		T.push(i);							//将i节点进入T栈,形成逆拓扑序列	
		count++;							//统计已输出的顶点数 
		
		p = G->vertices[i].firstArc;
		while(p!=NULL)
		{
			k = p->adjvex;
			indegree[k]--;					//i号顶点已出栈,所以将i号顶点的每个邻接点的入度自减 
			if(indegree[k]==0)
				s.push(k);					//如果入度减为0,则入栈
			
			if(ve[i]+p->weight>ve[k])
				ve[k] =  ve[i]+p->weight;	//按拓扑顺序更新事件的最早发生事件 
			
			p = p->next; 
		}
	}
	
	if(count<G->vexnum)
		return -1;							//存在回路 
	else
		return 0;
}

//求关键路径(AOE网,边表示活动的网) 
int CriticalPath(ALGraph *G) 
{
	int i,j,k;
	int dut,ei,li;
	int vl[MAX];							//每个事件的最晚发生事件
	ArcNode *p;
	stack<int> T;
	
	if(TopoSort(G,T))						//求事件的最早发生时间和逆拓扑序列 
		return -1; 
		
	for(i=0;i<G->vexnum;i++) 
		vl[i] = ve[G->vexnum-1];			//将各事件的最迟发生事件初始化为汇点的最早发生时间
	
	while(!T.empty())						//按逆拓扑序列求各事件的最晚发生时间
	{
		j = T.top();
		T.pop();														
		
		p = G->vertices[j].firstArc;
		while(p!=NULL)						//遍历整个栈 
		{
			k = p->adjvex;
			dut = p->weight;
			if(vl[k]-dut<vl[j])
				vl[j] = vl[k]-dut;			 
			
			p = p->next; 
		}
	} 
	cout<<"关键活动的相关信息如下:"<<endl;
	
	cout<<"活动"<<setw(16)<<"最早发生时间"<<setw(16)<<"最晚发生时间"<<setw(10)<<"持续时间"<<endl;  
	for(j =0;j<G->vexnum;j++)				//扫描每一条弧,求出e(i),l(i),找出关键路径 
	{
		p = G->vertices[j].firstArc;				
		while(p)
		{
			k = p->adjvex;
			dut = p->weight;
			ei = ve[j];						//活动的最早发生时间
			li = vl[k]-dut;					//活动的最晚发生时间 
			if(ei==li)						//输出关键活动的相关信息(ei,li,dut) 
			{
				cout<<"("<<G->vertices[j].data<<","<<G->vertices[k].data<<")"<<setw(10)<<ei
				<<setw(14)<<li<<setw(14)<<dut<<endl;
			} 
			
			p = p->next;
		}
	}
	
	return 0;
}

/*
a b c d e f g h i 

a b 6
a c 4
a d 5
b e 1
c e 1
d f 2
e g 9
b h 7
f h 4
g i 2
h i 4
*/

技术分享

关键路径

标签:数据结构   图论   算法   关键路径   aoe网   

原文地址:http://blog.csdn.net/huolang_vip/article/details/46564793

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!