【数据结构/c++】求解有向无环图DAG的关键路径

#include<cstring>//memset头文件 
#include<algorithm>//fill头文件 
#include<vector>
#include<stdio.h>
#include<stack>
#include<queue> 
using namespace std;
const int MAXV=510;
struct Node{
	int v,w;
	Node(int _v,int _w):v(_v),w(_w) {}
};
vector<Node> G[MAXV];
int ve[MAXV],vl[MAXV];//事件最早发生时间、最迟发生时间 
int inDegree[MAXV];//入度 
int n,m;

stack<int> topOrder;//拓扑序列 
//拓扑排序,求ve 
bool topological(){
	queue<int> q;
	for(int i=0;i<n;i++){//初始化 
		if(inDegree[i]==0){
			q.push(i);
		}
	}
	while(!q.empty()){
		int u=q.front();
		q.pop();
		topOrder.push(u);//将u加入拓扑序列 
		for(int i=0;i<G[u].size();i++){
			int v=G[u][i].v;
			inDegree[v]--;
			if(inDegree[v]==0){
				q.push(v);
			}
			if(ve[u]+G[u][i].w>ve[v]){  //用ve[u]更新ve[v] 
				ve[v]=ve[u]+G[u][i].w;
			}
		}
	}
	if(topOrder.size()==n) return true;
	else return false;
}
//关键路径 
int CriticalPath(){
	memset(ve,0,sizeof(ve));
	if(topological()==false){//有环 
		return -1;
	}
	fill(vl,vl+n,ve[n-1]);
	//出栈即逆拓扑排序,求vl 
	while(!topOrder.empty()){
		int u=topOrder.top();
		topOrder.pop();
		for(int i=0;i<G[u].size();i++){
			int v=G[u][i].v;
			if(vl[v]-G[u][i].w<vl[u]){ //用vl[v]更新vl[u] 
				vl[u]=vl[v]-G[u][i].w;
			}
		} 
	}
	//遍历所有边,计算活动的最早开始时间和最迟开始时间
	for(int u=0;u<n;u++){
		for(int i=0;i<G[u].size();i++){
			int v=G[u][i].v,w=G[u][i].w;
			int e=ve[u],l=vl[v]-w;
			if(e==l) printf("%d->%d\n",u,v);//关键活动 
		}
	}
	return ve[n-1];//关键路径长度 
}

int main(){
	scanf("%d%d",&n,&m);
	for(int i=0;i<n;i++){
		scanf("%d",&inDegree[i]);
	}
	int u,v,w;
	for(int i=0;i<m;i++){
		scanf("%d%d%d",&u,&v,&w);
		G[u].push_back(Node(v,w));			
	}
	printf("关键路径长度:%d",CriticalPath());
	return 0;
} 

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值