关键路径
- 目标是求每一个活动的最早开始时间和最迟开始时间
- ve[i]=max(ve[ik]+length[r]);k是i的前驱结点
- vl[i]=min(vl[ki]-length[r];k是i的后继结点
- e[i]=ve[i]
- l[i]=vl[ki]-length[r]k是r的邻接点
- 拓扑排序可以保证在求ve[i]时前驱结点都是正确的
- 然后求vl[i]时可以使用逆拓扑排序
代码
#include<vector>
#include<queue>
#include<stack>
using namespace std;
const int max_n = 30;
const int max_e = 30;
int n;//结点(事件)个数
int ind[max_n];
queue<int>q;
stack<int>order;
struct edge
{
int d;
int dis;
};
vector<edge>G[max_n];
int ve[max_n] = { 0 };//事件的最早开始时间
int vl[max_n];//事件的最迟开始时间
int e[max_e];//活动的最早开始时间
int l[max_e];//活动的最迟开始时间
void topologicalSort()
{
//计算入度
//入度为0的入队(在关键路径中一般只有一个 即源点)
for (int i = 0; i < n; i++)
{
if (ind[i] == 0)
q.push(i);
}
//
while (!q.empty())
{
int head = q.front();
q.pop();
order.push(head);
//将与之相连的入度为0的入队
for (int i = 0; i < G[head].size(); i++)
{
int v = G[head][i].d;
int dis = G[head][i].dis;
ind[v]--;
if (ind[v] == 0)
q.push(v);
//更新后面的ve
if (ve[v] < ve[head] + dis)
{
ve[v] = ve[head] + dis;
}
}
}
}
void Cal()
{
fill(vl,vl+n, ve[order.top()]);
if (order.empty())
{
vl[order.top()] = ve[order.top()];
}
while (!order.empty())
{
int v = order.top();
order.pop();
for (int i = 0; i < G[v].size(); i++)
{
int u = G[v][i].d;//v的后继结点
if (vl[v] > vl[u] - G[v][i].dis)
{
vl[v] = vl[u] - G[v][i].dis;
}
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < G[i].size(); j++)
{
int e = ve[i], l = vl[G[i][j].d]- G[i][j].dis;
if (e == l)
printf("%d->%d
", i, G[i][j].d);
}
}
//ve[n-1]是关键路劲长度
}