测试用例:顶点数量n,路径数量m
接下来m行:format:顶点a->顶点b 路径长度
6 8
0 1 3
0 2 2
0 3 2
2 3 5
1 4 3
3 5 2
2 5 3
4 5 1
关键路径一定是有向无环图
代码段
#include <cstdio>
#include <cstring>
#include <iostream>
#include <math.h>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <map>
#include <vector>
#include <set>
#include <stack>
#include <queue>
using namespace std;
const int maxn = 10010;
struct node{
int v,w;//编号
};
int indegree[maxn]={0};
//事件最早发生时间,事件最晚发生时间
int ve[maxn],vl[maxn];
//g[i]中保存了i指向的顶点node,其中有指向的顶点编号以及该边权重
vector<node> g[maxn];
stack<int> topOrder;
int n,m;
bool tologicalSort(){
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();
for(int i=0;i<g[u].size();i++){
int v=g[u][i].v;
indegree[v]--;
if(indegree[v]==0){
q.push(v);
}
//ve[v] = max(ve[v的前驱u]+length(u,v));
//根据拓扑顺序,求最早事件发生的最早时间
if(ve[u]+g[u][i].w>ve[v]){
ve[v] = ve[u]+g[u][i].w;
}
}
topOrder.push(u);
}
if(topOrder.size()==n) return true;
else return false;
}
int CriticalPath(){
memset(ve,0,sizeof(ve));
if(!tologicalSort()) return -1;
fill(vl,vl+n,ve[n-1]);//ve[n-1]是最长路径长度
while(!topOrder.empty()){
int u = topOrder.top();
topOrder.pop();
for(int i=0;i<g[u].size();i++){
int v = g[u][i].v;
//逆拓扑排序,从后往前计算事件最晚开始时间
//vl[u] = min(vl[后继v]-length[u,v])
if(vl[u]>vl[v]-g[u][i].w){
vl[u] = vl[v]-g[u][i].w;
}
}
}
//遍历邻接表所有边,计算所有活动的最早开始时间最晚开始时间
//e==l时,是关键活动 (路径)
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<m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
node Node;
Node.v = b;
Node.w = c;
g[a].push_back(Node);
indegree[b]++;
}
int a =CriticalPath();
return 0;
}