三步走:
- 求事件(顶点)的ve和vl;
- 求活动(边)的e和l;
- e与l相统的活动即为关键活动。
1.求ve
const int maxn = 500 + 10;
const int INF = 0x3fffffff;
//keypath
struct edge {
int u, v, weight;
};
stack<int> topoorder;
int indegree[maxn], n;
int ve[maxn], vl[maxn], e[maxn], l[maxn];
vector<edge> adj[maxn];
bool topologicalsort() {
//1
queue<int> q;
for (int i = 0; i < n; i++)
if (indegree[i] == 0)
q.push(i);
//2
while (!q.empty()) {
int u = q.front();
q.pop();
topoorder.push(u);
//3
for (int i = 0; i < adj[u].size(); i++) {
int v = adj[u][i].v;
indegree[v]--;
if (indegree[v] == 0)
q.push(v);
//4 所有前驱活动都完成,v才能开始,所以必须取最大值
if (ve[u] + adj[u][i].weight > ve[v])
ve[v] = ve[u] + adj[u][i].weight;
}
}
if (topoorder.size() == n)return true;
return false;
}
2.求vl(逆拓扑排序,直接将拓扑排序逆序即可)并求关键路径
int criticalpath() {
memset(ve, 0, sizeof(ve));
if (topologicalsort == false)
return -1;
fill(vl, vl + n, ve[n - 1]);
while (!topoorder.empty()) {
int u = topoorder.top();
topoorder.pop();
for (int i = 0; i < adj[u].size(); i++) {
int v = adj[u][i].v;
if (vl[v] - adj[u][i].weight < vl[u])
vl[u] = vl[v] - adj[u][i].weight;
}
}
for (int u = 0; u < n; u++) {
for (int i = 0; i < adj[u].size(); i++) {
int v = adj[u][i].v, w = adj[u][i].weight;
int e = ve[u], l = vl[v] - w;
if (e == l)
printf("%d->%d\n", u, v);
}
}
return ve[n - 1];//返回关键路径长度
}
整体代码:
#include <iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<string.h>
using namespace std;
#pragma warning(disable:4996)
#include<string>
#include<stack>
#include<map>
#include<queue>
#include<set>
const int maxn = 500 + 10;
const int INF = 0x3fffffff;
//criticalpath
struct edge {
int u, v, weight;
};
stack<int> topoorder;
int indegree[maxn], n;
int ve[maxn], vl[maxn], e[maxn], l[maxn];
vector<edge> adj[maxn];
bool topologicalsort() {
//1
queue<int> q;
for (int i = 0; i < n; i++)
if (indegree[i] == 0)
q.push(i);
//2
while (!q.empty()) {
int u = q.front();
q.pop();
topoorder.push(u);
//3
for (int i = 0; i < adj[u].size(); i++) {
int v = adj[u][i].v;
indegree[v]--;
if (indegree[v] == 0)
q.push(v);
//4 所有前驱活动都完成,v才能开始,所以必须取最大值
if (ve[u] + adj[u][i].weight > ve[v])
ve[v] = ve[u] + adj[u][i].weight;
}
}
if (topoorder.size() == n)return true;
return false;
}
int criticalpath() {
memset(ve, 0, sizeof(ve));
if (topologicalsort == false)
return -1;
fill(vl, vl + n, ve[n - 1]);
while (!topoorder.empty()) {
int u = topoorder.top();
topoorder.pop();
for (int i = 0; i < adj[u].size(); i++) {
int v = adj[u][i].v;
if (vl[v] - adj[u][i].weight < vl[u])
vl[u] = vl[v] - adj[u][i].weight;
}
}
for (int u = 0; u < n; u++) {
for (int i = 0; i < adj[u].size(); i++) {
int v = adj[u][i].v, w = adj[u][i].weight;
int e = ve[u], l = vl[v] - w;
if (e == l)
printf("%d->%d\n", u, v);
}
}
return ve[n - 1];//返回关键路径长度
}