关键路径

关键路径的求法一般是针对有向无环图的,常用来解决工程中的问题,前面我们学过Bellman和SPFA算法,如果我们给每条边变成相反数就可以求解关键路径了,当然关键路径不止一种求法,数据结构中给出的关键路径求法的优势在于其更快,利用了ve,vl数组,下面是其代码。

#include<iostream>
#include<stack>
#include<queue> 
#include<vector>
#include<algorithm>
using namespace std;

const int maxv=1001;

struct node{
	int v,w;
};
vector<node>Adj[maxv];//定义邻接表
int indegree[maxv];//存储入度 

int ve[maxv],vl[maxv];
stack<int>s;//存储拓扑排序,逆向输出为逆拓扑排序


bool topological(int n) {  //拓扑排序,生成事件最早开始时间 
	fill(ve,ve+n+1,0);//从前向后推 
	queue<int>q;
	for(int i=1;i<=n;i++) 
	if(indegree[i]==0)
	q.push(i);
	while(!q.empty()){
		int t=q.front();q.pop();
	    s.push(t);
	    for(int i=0;i<Adj[t].size();i++){
	    	int x=Adj[t][i].v,w=Adj[t][i].w;
	    	indegree[x]--;
	    	if(indegree[x]==0)
	    	q.push(x);
	    	if(ve[t]+w>ve[x])//x位置的最早时间等于之前最长的路 
	    	ve[x]=ve[t]+w;
		}
	}
	if(s.size()==n)return true;
	return false;
}


int createvl(int n) {//生成事物的最迟开始时间 
   int maxlength=0;
   for(int i=1;i<=n;i++)   //找到汇点 
   if(ve[i]>maxlength)
   maxlength=ve[i];
	fill(vl,vl+n+1,maxlength);//从后往前推 
	while(!s.empty()){
		int t=s.top() ;s.pop(); 
		for(int i=0;i<Adj[t].size();i++)
		{   
		    int x=Adj[t][i].v;
			if(vl[x]-Adj[t][i].w<vl[t]) 
			//t处最迟开始时间等于 之后路径最迟开始时间的最小值 
			vl[t]=vl[x]-Adj[t][i].w;
		}
	}	
	return maxlength;
}


int criticalpath(int n) {
	
	if(topological(n)==false)
	return-1;
 int  k=createvl(n);
	
	for(int i=1;i<=n;i++)
	for(int j=0;j<Adj[i].size();j++){
		int x=Adj[i][j].v,w=Adj[i][j].w;
		int e=ve[i],l=vl[x]-w;
		if(e==l)
		printf("%d->%d\n",i,x);
	}
	return k; //返回路径和 
}

 int main(){
 	int n,m,x,y,w;
 	scanf("%d%d",&n,&m);
 	node t;
 	fill(indegree,indegree+n+1,0);
 	for(int i=1;i<=m;i++){
 		scanf("%d%d%d",&x,&y,&w);
 		t.v=y;t.w=w;
 		Adj[x].push_back(t);
 		indegree[y]++;
	 }
	 criticalpath(n);
 	
 	return 0;
 }

还有动态规划也可以求关键路径,等接下来学习之后补充。

相关推荐
©️2020 CSDN 皮肤主题: 1024 设计师:白松林 返回首页