AOE网的关键路径

#include<iostream>
#include<string.h>
using namespace std;
#define Maxn 100		//顶点最大数
#define Maxm 200		//边数最大数
struct arcnode{
	int to,dur,no;		//边指向点,以及权重(时间),活动序号 
	arcnode *next; 
}; 
int n,m;				//顶点数,边数
arcnode *list1[Maxn];	//出边邻接表
arcnode *list2[Maxm];	//入边邻接表
int count1[Maxn] ;		//入度
int count2[Maxm] ;		//出度
int ee[Maxn];			//各事件的最早可能开始时间 
int le[Maxn];			//各事件的最迟允许开始时间
int e[Maxm];			//各活动的最早可能开始时间
int l[Maxm];			//各活动的最迟允许开始时间
void create(){			//构建邻接表 
	int i,u,v,w;		//循环变量以及边起点 边终点 边时间 
	printf("请输入顶点数和边数\n"); 
	scanf("%d%d",&n,&m);//读入顶点数和边数
	memset(list1,0,sizeof(list1)) ;//初始化数组 
	memset(list2,0,sizeof(list2)) ;
	memset(count1,0,sizeof(count1));
	memset(count2,0,sizeof(count2));
	arcnode *temp1 ,*temp2;
	printf("请输入边起点 边终点 边时间\n"); 
	for(i=0;i<m;i++){
		scanf("%d%d%d",&u,&v,&w);//读入边的起点和终点
		count1[v]++;
		count2[u]++;
		temp1=new arcnode;
		temp1->to=v;
		temp1->no=i+1;
		temp1->dur=w;
		temp1->next=NULL;
		if(list1[u]==NULL)list1[u]=temp1;
		else{temp1->next=list1[u];//头插法构建出边邻接表
			list1[u]=temp1;
		}
		temp2=new arcnode;
		temp2->to=u;
		temp2->no=i+1;
		temp2->dur=w;
		temp2->next=NULL;
		if(list2[v]==NULL)list2[v]=temp2;
		else{temp2->next=list2[v];
			list2[v]=temp2;
		} 
		
	}
	printf("打印AOE网的邻接表逻辑图\n"); 
	for(i=0;i<n;i++){
		temp1=list1[i];
		printf("%d %d",count1[i],i);
		cout<<"-->";
		while(temp1!=NULL){
			printf("[%d %d]",temp1->to,temp1->dur);
			temp1=temp1->next;
			
		}
		printf("\n");
		
	}
	printf("\n");
	
}
void CriticalPath(){//关键路径算法 
	int i,j,k;
	arcnode *temp1,*temp2;
	memset(ee,0,sizeof(ee));
	memset(le,0,sizeof(le));
	//拓扑排序 
	int top1=-1;
	int stack[200];		//一个栈 
	//拓扑排序 
	for(i=0;i<n;i++){
		if(count1[i]==0)stack[++top1]=i; 
	}
	while(top1>-1){
		i=stack[top1--];
		temp1=list1[i];
		while(temp1!=NULL){
			j=temp1->to;
			count1[j]--;
			if(ee[i]+temp1->dur>ee[j])ee[j]=ee[i]+temp1->dur;
			if(count1[j]==0)stack[++top1]=j;
			temp1=temp1->next;
		}
	}
	//运用逆邻接表来进行逆拓扑排序 
	
	int top2=-1;
	for(i=0;i<n;i++){
		le[i]=ee[n-1];
		if((count2[i]==0))stack[++top2]=i;
	} 
	while(top2>-1){
		i=stack[top2--];
		temp2=list2[i];
		while(temp2!=NULL){
			j=temp2->to;
			count2[j]--;
			if(le[i]-temp2->dur<le[j])le[j]=le[i]-temp2->dur;
			if(count2[j]==0)stack[++top2]=j;
			temp2=temp2->next;
		}
	}
	memset(e, 0, sizeof(e));
 	memset(l, 0, sizeof(l));
	printf("关键路径如下\n");
	// 
	for(i=0;i<n;i++){
		temp1=list1[i];
		while(temp1!=NULL){
			j=temp1->to;
			k=temp1->no;
			e[k]=ee[i];
			l[k]=le[j]-temp1->dur;
			if(e[k]==l[k]){
				printf("v%d : %d->%d\n",k,i,j);
				
			}
			temp1=temp1->next;
		}
	} 
	printf("\n");
	printf("最短时间:%d",ee[n-1]);
}


int main(){
	create();
	CriticalPath() ;
	
	
	
	
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

coding小黄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值