0
点赞
收藏
分享

微信扫一扫

图论之关键路径

栖桐 2022-05-04 阅读 62
图论

浅看拓扑序列

AOE:

有向无环图中的顶点表示活动或事件,有向边(弧)表示了事件发生的先后关系

注:(A---->B 这个为弧,A为弧尾,B为弧头)

拓扑序列:

给定一个包含一个有向图所有顶点的序列,如果图中任意两个顶点Vi到Vj有一条路径,且在该序列中vi排在vj的前面

注:该序列不唯一

应用:

判断图是否存在环(用一个计数器记录每次出栈或出队次数,小于顶点数则存在环)

求关键路径

算法步骤

1、对于每一个点用一个数组d[i]记录i号顶点的入度

2、一遍循环找到入度为0 的顶点入栈(队列)

3、循环:如果栈(队列)非空

{

取出栈顶(队首)t,输出(记录)

将领接表中以t为起点的边的终点的入度-1(相当于删除该顶点即它的所有出边)

如果该终点的入度为0 则入栈(入队)

}

注:手写数组队列时,整个过程结束后,队列从0到队尾所保存的就是拓扑序列

模板:

关键路径:

AOE:

有向图中顶点表示事件,边表示活动,边权表示活动持续时间

源点:

入度为0的事件

汇点:

出度为0的事件

关键路径:

 

 

 测试数据:

6 8 
0 1 2
0 2 15
1 3 10
1 4 19
2 1 4
2 4 11
3 5 6
4 5 5

 

bool creaticalpath()
{
	if(topsort()){
		cout<<"拓扑序列为:"<<endl;
		for(int i=0;i<n;i++)
		cout<<topo[i]<<"\t";
		cout<<endl; 
	}
	else {
		cout<<"该图有环,无拓扑序列"<<endl;
		return 0; 
	}
	for(int i=0;i<n;i++)//初始化最早发生时间 
	ve[i]=0;
	for(int j=0;j<n;j++){//求每个事件最早发生时间 
		int u=topo[j];
		for(int i=h[u];i;i=ne[i])
		{
			int v=e[i],t=w[i];
			ve[v]=max(ve[u]+w,ve[v]);
		}
	}
	for(int i=0;i<n;i++)//初始化每个事件最迟发生时间 
		vl[i]=ve[n-1];
		for(int j=n-1;j>=0;j--)
		{
			int u=topo[j];
			for(int i=h[u];i;i=ne[i])
			{
				int v=e[i],t=w[i];
			  vl[u]=min(vl[u],vl[v]+t);
			}
		}
		cout<<"事件的最早发生时间和最迟发生时间:"<<endl;
		for(int i=0;i<n;i++)
		cout<<ve[i]<<"\t"<<vl[i]<<endl;
		for(int u=0;u<n;u++){//对u的弧尾所有活动求最早开始时间和最迟开始时间 
			for(int i=h[u];i;i=ne[i]){
				int v=e[i],t=w[i];
				int estart=ve[u];
				int end=vl[v]-t;
				if(estart==end)
				cout<<"<"<<u<<","<<v<<">"<<endl;
			}
		} 
		return 1;
}

 

 

 

 

 

举报

相关推荐

0 条评论