AOE关键路径-基于c++十字链表实现

AOE网,带权有向图,边表示活动,顶点表示事件,既有活动之间的先后制约关系,又有活动的消耗,从源点到汇点的带权路径长度最大的路径称为关键路径,其中的活动称为关键活动。

#include<iostream>
#include<stack>
using namespace std;
const int maxNum = 100;
typedef struct arcNode {    //弧结点类型
	int tail;				//弧尾下标
	int head;				//弧头下标
	struct arcNode*hlink;	//指针,指向同弧头的弧
	struct arcNode*tlink;	//指针,指向同弧尾的弧
	int w;
}arcNode;
typedef struct vexNode
{
	char data;				//指点数据
	arcNode *firstIn;		//指针,指向第一个入弧
	arcNode *firstout;		//指针,指向第一个出弧
};
typedef struct {
	vexNode vexs[maxNum];
	int vexnum, edgenum;	//顶点数量,边数量
}OLGraph;
OLGraph g;
int topo[maxNum];
int LocateVex(char c)
{
	for (int i = 0; i < g.vexnum; i++)
	{
		if (g.vexs[i].data == c)
		{
			return i;
		}
	}
	return -1;
}
void insertedge(char a, char b,int w)
{
	int ai = LocateVex(a);
	int bi = LocateVex(b);
	arcNode* an = new arcNode;						//生成一条新弧
	an->tlink = g.vexs[ai].firstout;		//顶点第一个出弧更新,尾插入
	an->head = bi;						//由ai->bi
	an->tail = ai;
	an->w = w;									//ai->bi的权重
	g.vexs[ai].firstout = an;			//顶点第一个出弧更新,尾插入
	an->hlink = NULL;
	if (g.vexs[bi].firstIn == NULL)
	{
		g.vexs[bi].firstIn = an;
	}
	else
	{
		arcNode* curArc = g.vexs[bi].firstIn;		//找到最后一个入弧
		while (curArc->hlink != NULL)
		{
			curArc = curArc->hlink;
		}
		curArc->hlink = an;
	}
}
void CreateOLGraph() {
	cout << "请输入顶点数量和边数:" << endl;
	cin >> g.vexnum >> g.edgenum;
	cout << "输入对应的顶点:" << endl;
	for (int i = 0; i < g.vexnum; i++)
	{
		cin >> g.vexs[i].data;
		g.vexs[i].firstIn = NULL;
		g.vexs[i].firstout = NULL;
	}
	cout << "输入要插入的边" << endl;
	int m = g.edgenum;
	while (m > 0)
	{
		char a, b;
		int w;
		cin >> a >> b>>w;
		insertedge(a, b,w);
		m--;
	}
}
bool TopologicalSort()
{
	int* indegree = new int[g.vexnum];			//入度数组
	int k = 0;
	stack<int> stack;
	arcNode* an;
	//初始化入度数组
	for (int i = 0; i < g.vexnum; i++)
	{
		int m = 0;
		an = g.vexs[i].firstIn;
		while (an != NULL)
		{
			m++;
			an = an->hlink;
		}
		indegree[i] = m;
	}
	//将入度为0的顶点索引加入栈中,当栈为空结束
	for (int i = 0; i < g.vexnum; i++)
	{
		if (indegree[i] == 0)
			stack.push(i);
	}
	while (stack.size() > 0)
	{
		int t = stack.top();
		stack.pop();
		topo[k] = t;
		//把t顶点的所有出度的顶点入度全部减一
		an = g.vexs[t].firstout;
		while (an != NULL)
		{
			indegree[an->head]--;
			if (indegree[an->head] == 0)
			{
				stack.push(an->head);
			}
			an = an->tlink;
		}
		k++;
	}
	if (k < g.vexnum)
		return false;
	else return true;
}
void CriticalPath()
{
	int* ve = new int[g.vexnum];					//顶点最早开始时间
	int* vl = new int[g.vexnum];					//顶点最迟开始时间
	arcNode* an;									//弧
	if (!TopologicalSort())
	{
		cout << "该图有环,无拓扑排序!" << endl;	
		return;
	}
	//初始化各顶点最早开始时间为0
	for (int i = 0; i < g.vexnum; i++)
	{
		ve[i] = 0;
	}
	//获取各顶点最早开始时间,拓扑排序从前往后
	for (int i = 0; i < g.vexnum; i++)
	{
		an = g.vexs[topo[i]].firstout;
		while (an != NULL)
		{
			if (ve[an->head] < ve[topo[i]] + an->w)
				ve[an->head] = ve[topo[i]] + an->w;
			an = an->tlink;
		}
	}
	//初始化各顶点最迟开始时间
	for (int i = g.vexnum-1; i >=0; i--)
	{
		vl[i] = ve[g.vexnum - 1];
	}
	//获取各顶点最迟开始时间,拓扑排序从后往前
	for (int i = g.vexnum-1; i >=0 ; i--)
	{
		an = g.vexs[topo[i]].firstout;
		while (an != NULL)
		{
			if (vl[topo[i]] > vl[an->head] - an->w)
				vl[topo[i]] = vl[an->head] - an->w;
			an = an->tlink;
		}
	}
	//计算活动的最早和最迟,最早=最迟就是关键活动路径,拓扑排序从前往后
	cout << "关键活动路径为:" << endl;
	for (int i = 0; i < g.vexnum; i++)
	{
		int e, l;
		an = g.vexs[topo[i]].firstout;
		while (an != NULL)
		{
			e = ve[topo[i]];
			l = vl[an->head] - an->w;
			if (e == l)
			{
				cout <<"<"<< topo[i] << "," << an->head << "> ";
				break;
			}
			an = an->tlink;
		}
	}
}
int main()
{
	CreateOLGraph();
	CriticalPath();
	return 0;
}

测试用例
6 8
0 1 2 3 4 5
0 1 2
0 2 15
1 3 10
1 4 19
2 1 4
2 5 11
3 5 6
4 5 5

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
AOE网络(Activity On Edge Network)是一种用来描述工程项目的网络模型,其中每个节点表示一个活动,每条边表示活动之间的先后关系。关键路径是指在保证项目完成时间最短的前提下,所有活动中耗时最长的路径。以下是用C++实现关键路径的示例代码: ```c++ #include <iostream> #include <queue> #include <vector> using namespace std; const int MAXN = 10010; const int INF = 0x7fffffff; struct Edge { int to, w; Edge(int to, int w) : to(to), w(w) {} }; vector<Edge> G[MAXN]; // 存储图 int inDegree[MAXN]; // 存储入度 int earliest[MAXN]; // 存储最早开始时间 int latest[MAXN]; // 存储最晚开始时间 int n, m; // n为节点数,m为边数 void topsort() { queue<int> q; for (int i = 1; i <= n; ++i) { if (inDegree[i] == 0) { q.push(i); earliest[i] = 0; } } while (!q.empty()) { int u = q.front(); q.pop(); for (auto e : G[u]) { int v = e.to, w = e.w; inDegree[v]--; if (inDegree[v] == 0) { q.push(v); } earliest[v] = max(earliest[v], earliest[u] + w); } } } int criticalPath() { topsort(); int res = 0; for (int u = 1; u <= n; ++u) { for (auto e : G[u]) { int v = e.to, w = e.w; latest[u] = max(latest[u], latest[v] - w); } } for (int u = 1; u <= n; ++u) { for (auto e : G[u]) { int v = e.to, w = e.w; if (latest[v] - earliest[u] - w == 0) { res = max(res, latest[v]); } } } return res; } int main() { cin >> n >> m; for (int i = 1; i <= m; ++i) { int u, v, w; cin >> u >> v >> w; G[u].push_back(Edge(v, w)); inDegree[v]++; } cout << criticalPath() << endl; return 0; } ``` 在上述代码中,我们使用vector存储图,使用队列进行拓扑排序。在拓扑排序的过程中,我们计算每个节点的最早开始时间。之后,我们再次遍历图,计算每个节点的最晚开始时间,并且计算关键路径的长度。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JustEasyCode

谢谢您

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值