关键路径 PTA 6-32

先说思路,答案是第一行代码,第二段代码是思考,题目在最后;

思路:先是正常分别用两个for循环分别求出每个结点的最早开始时间和最晚开始时间,而后创建一个栈,并把topo[0]---也就是起始点压入栈,而后类似深度优先搜索,只要栈不为空,每次取出栈顶元素v,并且用p遍历一遍v在图中指向的结点,如果该结点最晚开始时间==最早开始时间就把这个结点压入栈(用队列也可以实现输出路径,不过输出顺序不一样,用队列类似广度优先搜索,这道题对输出顺序有要求,我把队列实现放在第二段代码,可以了解一下)

答案代码:

int CriticalPath(ALGraph G){//栈实现,对多条关键路径深度优先输出 
	TopologicalOrder(G,topo);
	int i,v,flag=1;
	struct ArcNode* p;
	ve[topo[0]]=0;vl[topo[0]]=0;
	for(i=0;i<G.vexnum;i++){//最早开始时间  正推 
		v=topo[i];
		p=G.vertices[v].firstarc;
		while(p){
			if(ve[p->adjvex]<ve[v]+p->weight) ve[p->adjvex]=ve[v]+p->weight;
			p=p->nextarc; 
		}
	}
	vl[topo[G.vexnum-1]]=ve[topo[G.vexnum-1]];//最后一个结点的最早开始时间等于最晚开始时间 
	for(i=G.vexnum-1;i>=0;i--){//最晚开始时间 反推 
		v=topo[i];
		p=G.converse_vertices[v].firstarc;
		while(p){
			if(vl[p->adjvex]==0||(vl[p->adjvex]>vl[v]-p->weight)) vl[p->adjvex]=vl[v]-p->weight;
			p=p->nextarc;
		} 
	}
	//应该用栈实现,先把最前1压入栈,不用collected ,DFS的味道 
	int stack[G.vexnum],top=-1;
	stack[++top]=topo[0];
	while(top!=-1){
		v=stack[top--];
		p=G.vertices[v].firstarc;
		while(p){
			if(vl[p->adjvex]==ve[p->adjvex]){
				if(flag) flag=0;
				else printf(","); 
				printf("%c->%c",G.vertices[v].data,G.vertices[p->adjvex].data);
				stack[++top]=p->adjvex;
			} 
			p=p->nextarc;
		}
	}
	return 1;
} 

队列实现:(这个原理对,但不是这道题的正确答案,因为顺序错了)

int CriticalPath(ALGraph G){//用队列逻辑上也对,但是这道题对顺序有要求,用队列就是广度优先 
	TopologicalOrder(G,topo);
	int i,v,flag=1;
	struct ArcNode* p;
	ve[topo[0]]=0;vl[topo[0]]=0;
	for(i=0;i<G.vexnum;i++){//最早开始时间  正推 
		v=topo[i];
		p=G.vertices[v].firstarc;
		while(p){
			if(ve[p->adjvex]<ve[v]+p->weight) ve[p->adjvex]=ve[v]+p->weight;
			p=p->nextarc; 
		}
	}
	vl[topo[G.vexnum-1]]=ve[topo[G.vexnum-1]];//最后一个结点的最早开始时间等于最晚开始时间 
	for(i=G.vexnum-1;i>=0;i--){//最晚开始时间 反推 
		v=topo[i];
		p=G.converse_vertices[v].firstarc;
		while(p){
			if(vl[p->adjvex]==0||(vl[p->adjvex]>vl[v]-p->weight)) vl[p->adjvex]=vl[v]-p->weight;
			p=p->nextarc;
		} 
	}
	//应该用队列实现,先把最前1入队,不用collected ,有点BFS的味道 
	int queue[G.vexnum],f=-1,r=-1;
	queue[++r]=topo[0];
	while(f!=r){
		v=queue[++f];
		p=G.vertices[v].firstarc;
		while(p){
			if(vl[p->adjvex]==ve[p->adjvex]){
				if(flag) flag=0;
				else printf(","); 
				printf("%c->%c",G.vertices[v].data,G.vertices[p->adjvex].data);
				queue[++r]=p->adjvex;
			} 
			p=p->nextarc;
		}
	}
	return 1;
} 

题目:

试实现关键路径算法。函数int CriticalPath(ALGraph G)输出关键路径。

函数接口定义:

 

int CriticalPath(ALGraph G);

其中 G 是基于邻接表及逆邻接表存储表示的有向图。

裁判测试程序样例:

 
#include <iostream>
using namespace std;
#define MVNum 100    
#define BDNum MVNum * (MVNum - 1)
#define OK 1    
#define ERROR 0 
typedef char VerTexType;
typedef struct ArcNode{
    int adjvex;
    int weight;
    struct ArcNode *nextarc;
}ArcNode; 

typedef struct VNode{ 
    VerTexType data; 
    ArcNode *firstarc; 
}VNode, AdjList[MVNum];

typedef struct{ 
    AdjList vertices; //邻接表 
    AdjList converse_vertices;//逆邻接表
    int vexnum, arcnum; 
}ALGraph;

int indegree[MVNum];//数组indegree存放个顶点的入度
int ve[BDNum];    //事件vi的最早发生时间
int vl[BDNum];    //事件vi的最迟发生时间
int topo[MVNum];    //记录拓扑序列的顶点序号

int CreateUDG(ALGraph &G); //实现细节隐藏
void FindInDegree(ALGraph G,int indegree[]);//获取各个顶点的入度,indegree存放个顶点的入度,函数实现细节隐藏
int TopologicalOrder(ALGraph G , int topo[]);//拓扑排序,topo存放拓扑序列,函数实现细节隐藏
int CriticalPath(ALGraph G);
int main(){
    ALGraph G;
    CreateUDG(G);
    int *topo = new int [G.vexnum];
    CriticalPath(G);
    return 0;
}
/* 请在这里填写答案 */

输入样例:

第1行输入结点数vexnum和边数arcnum。第2行输入vexnum个字符表示结点的值,接下来依次输入arcnum行,每行输入2个字符v和u,表示v到u有一条有向边。

9 11
1 2 3 4 5 6 7 8 9
1 2 6
1 3 4
1 4 5
2 5 1
3 5 1
4 6 2
5 7 9
5 8 7
6 8 4
7 9 2
8 9 4

输出样例:

输出关键路径。

1->2,2->5,5->8,5->7,7->9,8->9 

QQ截图20191125213124.png

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值