关键路径

关键路径

  • 目标是求每一个活动的最早开始时间和最迟开始时间
  • 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\n", i, G[i][j].d);
		}
	}
	//ve[n-1]是关键路劲长度
}
posted @ 2021-09-07 09:58  小帆敲代码  阅读(29)  评论(0编辑  收藏  举报