图的相关算法:拓扑排序和关键路径

拓扑排序

#include<iostream>
#include<vector>
#include<stack>
#include<string>
using namespace std;
struct EdgeNode {
	int adjvex;
	//int weight;
	struct EdgeNode* next;
};

struct VextexNode {
	int in;
	int name;
	EdgeNode* firstedge;
};

vector<int> Topsort(vector<VextexNode>data, int V_num)
{
	vector<int> ret;
	int count = 0;
	stack<VextexNode>s;
	for (int i = 0; i < V_num; i++)
	{
		if (data[i].in == 0)
		{
			s.push(data[i]);
		}
	}
	while (!s.empty())
	{
		count++;
		VextexNode temp = s.top();
		s.pop();
		for (EdgeNode* e = temp.firstedge; e; e = e->next)
		{
			data[e->adjvex].in--;
			if (data[e->adjvex].in == 0)
				s.push(data[e->adjvex]);
		}
		ret.push_back(temp.name);
	}
	if (count != V_num)
	{
		cout << "该图中存在环!" << endl;
	}
	return ret;
}
int main()
{
	int V_num;
	int E_num;
	cout << "请输入图中顶点的数目:" << endl;
	cin >> V_num;
	cout << "请输入图中边的数目:" << endl;
	cin >> E_num;
	vector<vector<int>>arc(V_num, vector<int>(V_num));
	cout << "请输入图中每一条边的信息:" << endl;
	for (int i = 0; i < E_num; i++)
	{
		int e1, e2;
		cin >> e1 >> e2;
		arc[e1][e2] = 1;
	}

	//拓扑排序

	//创建拓扑排序的邻接表
	vector<VextexNode>data(V_num);
	for (int i = 0; i < V_num; i++)
	{
		//cout << "请输入每个顶点的信息:" << end;
		data[i].name = i;
		data[i].firstedge = NULL;
		int count = 0;
		for (int j = 0; j < V_num; j++)
		{
			if (arc[i][j] == 1)
			{
				EdgeNode* E = new EdgeNode();
				E->adjvex = j;
				E->next = data[i].firstedge;
				data[i].firstedge = E;
			}
			if (arc[j][i] == 1)
				count++;
		}
		data[i].in = count;
	}

	//拓扑排序
	vector<int> str;
	str = Topsort(data, V_num);
	cout << "拓扑排序后的结果为:" << endl;
	for(int i = 0;i<str.size();i++)
	cout << str[i] << " ";
	cout << endl;
	system("pause");
	return 0;
}
  • 关键路径 
#include<iostream>
#include<stack>
#include<vector>
using namespace std;

struct EdgeNode {
	int weight;
	int ajdvex;
	struct EdgeNode* next;
};
struct VertexNode {
	int in;
	int name;
	struct EdgeNode* firstedge;
};
stack<VertexNode> Topsort(vector<VertexNode>adjList, int V_num, vector<int>& etv)
{
	stack<VertexNode>s;
	stack<VertexNode>ret;
	for (int i = 0; i < V_num; i++)
	{
		if (adjList[i].in==0)
		{
			s.push(adjList[i]);
		}
	}
	while (!s.empty())
	{
		VertexNode temp = s.top();
		s.pop();
		ret.push(temp);
		for (EdgeNode* e = temp.firstedge; e; e = e->next)
		{
			adjList[e->ajdvex].in--;
			if (adjList[e->ajdvex].in == 0)
			{
				s.push(adjList[e->ajdvex]);
			}
			if (etv[temp.name] + e->weight > etv[e->ajdvex])
				etv[e->ajdvex] = etv[temp.name] + e->weight;
		}
	}
	return ret;
}
void Keypath(vector<VertexNode>adjList, int V_num)
{
	vector<int>etv(V_num);
	stack<VertexNode>s;
	//拓扑排序,寻找etv
	s = Topsort(adjList, V_num, etv);
	vector<int>ltv(V_num, etv[s.top().name]);
	while (!s.empty())
	{
		VertexNode temp = s.top();
		s.pop();
		for (EdgeNode* e = temp.firstedge; e; e = e->next)
		{
			if (ltv[e->ajdvex] - e->weight < ltv[temp.name])
				ltv[temp.name] = ltv[e->ajdvex] - e->weight;
		}
	}
	for (int i = 0; i < V_num; i++)
	{
		for (EdgeNode* e = adjList[i].firstedge; e; e = e->next)
		{
			int ete = etv[i];
			int k = e->ajdvex;
			int lte = ltv[k] - e->weight;
			if (lte == ete)
			{
				cout << i << " " << k << endl;
			}
		}
	}
}
int main()
{
	int V_num, E_num;
	cout << "请输入图中点的数目:" << endl;
	cin >> V_num;
	cout << "请输入图中变得数目:" << endl;
	cin >> E_num;
	vector<vector<int>>arc(V_num, vector<int>(V_num, INT_MAX));
	cout << "请输入图中每一条边的信息:" << endl;
	for (int i = 0; i < E_num; i++)
	{
		int e1, e2, w;
		cin >> e1 >> e2 >> w;
		arc[e1][e2] = w;
	}
	//拓扑排序并且寻找每个节点最晚开始的时间
	vector<VertexNode>adjList(V_num);
	for (int i = 0; i < V_num; i++)
	{
		adjList[i].name = i;
		adjList[i].firstedge = NULL;
		int count = 0;
		for (int j = 0; j < V_num; j++)
		{
			if (arc[i][j] != INT_MAX)
			{
				EdgeNode* temp = new EdgeNode();
				temp->ajdvex = j;
				temp->weight = arc[i][j];
				temp->next = adjList[i].firstedge;
				adjList[i].firstedge = temp;
			}
			if (arc[j][i] != INT_MAX)
				count++;
		}
		adjList[i].in = count;
	}
	cout << "关键路径为:" << endl;
	Keypath(adjList, V_num);
	system("pause");
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值