关键路径算法

三步走:

  1. 求事件(顶点)的ve和vl;
  2. 求活动(边)的e和l;
  3. 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];//返回关键路径长度
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值