//关键路径,利用拓扑排序求解关键路径(图的邻接矩阵存储)
//关键路径即整个图中从起点到终点的最长距离,我们把顶点称为事件,边称为活动
//求解关键路径即求出所有事件的最早开始时间和最晚开始时间(假设总时长不推迟)
//若一活动的起点事件的最早开始时间=该活动终点事件的最晚开始时间-活动持续时间,该活动为关键活动
//关键路径上的所有活动都是关键活动
#include<iostream>
#include<stdlib.h>
#include<stack>
using namespace std;
#define MAX_VERTEX 10
#define MAX_WEIGHT 100
//邻接矩阵
typedef struct
{
int weight;
}AdjMatrix[MAX_VERTEX][MAX_VERTEX];
//图
struct Graph
{
int* head;
AdjMatrix adj;
int vn;
int en;
};
//给顶点数据返回顶点下标
int Located(Graph g, int x)
{
for (int i = 0; i < g.vn; i++)
if (g.head[i] == x)
return i;
return 100;
}
//邻接矩阵存储
void CreateGraph(Graph& g)
{
g.head = (int*)malloc(MAX_VERTEX * sizeof(int));
cout << "Input vertex numbers and edge numbers: ";
cin >> g.vn >> g.en;
for (int i = 0; i < g.vn; i++)
for (int j = 0; j < g.vn; j++)
g.adj[i][j].weight = MAX_WEIGHT;
//输入顶点与边
cout << "Input vertexs: " << endl;
for (int i = 0; i < g.vn; i++)
cin >> g.head[i];
for (int i = 0; i < g.en; i++)
{
cout << "Input the vertexs and the weight of the edge" << endl;
int a, b,w;
cin >> a >> b>>w;
g.adj[Located(g, a)][Located(g, b)].weight = w;
}
}
int InDegree[MAX_VERTEX];//入度数
int ve[MAX_VERTEX];//事件最早发生时间
int vl[MAX_VERTEX];//事件最晚发生时间
//初始化入度
void FindInDegree(Graph g)
{
for (int i = 0; i < g.vn; i++)
InDegree[i] = 0;
for (int i = 0; i < g.vn; i++)
for (int j = 0; j < g.vn; j++)
if(g.adj[i][j].weight!=MAX_WEIGHT)
InDegree[j]++;
}
//为配合求关键路径而修改过的拓扑排序
void TopoLogicalSort(Graph g,stack<int>&t)
{
stack<int>s;
FindInDegree(g);
for (int i = 0; i < g.vn; i++)
ve[i] = 0;
//将所有入度为0的顶点下标入栈
for (int i = 0; i < g.vn; i++)
if (!InDegree[i])
s.push(i);
while (!s.empty())
{
int v = s.top();
s.pop();
//将本应打印的顶点入栈,构造逆拓扑排序,为关键路径函数中从拓扑排序最后开始倒推vl做准备
t.push(v);
//将该顶点周边一圈顶点的入度-1,若有减完入度为0的直接入栈
for (int i = 0; i < g.vn; i++)
if (g.adj[v][i].weight != MAX_WEIGHT)
{
if (!(--InDegree[i]))
s.push(i);
//初始化ve
if (ve[i] < ve[v] + g.adj[v][i].weight)
ve[i] = ve[v] + g.adj[v][i].weight;
}
}
}
void CriticalPath(Graph g)
{
stack<int>t;
TopoLogicalSort(g,t);
//初始化vl为终点所用时间(最大值)
for (int i = 0; i < g.vn; i++)
vl[i] = ve[t.top()];
t.pop();
//通过逆拓扑排序求vl
while(!t.empty())
{
int j = t.top();
t.pop();
for (int k = 0; k < g.vn; k++)
if (g.adj[j][k].weight != MAX_WEIGHT && vl[j] > vl[k] - g.adj[j][k].weight)
vl[j] = vl[k] - g.adj[j][k].weight;
}
//打印关键活动(连起来就是关键路径)
cout << "Following critical activities:" << endl;
for (int i = 0; i < g.vn; i++)
for (int j = 0; j < g.vn; j++)
if (g.adj[i][j].weight != MAX_WEIGHT && ve[i] == vl[j] - g.adj[i][j].weight)
cout <<"from "<< g.head[i] << " to " << g.head[j] << endl;
}
int main()
{
Graph g;
CreateGraph(g);
CriticalPath(g);
}
关键路径,C++实现,图用邻接矩阵存储
最新推荐文章于 2024-08-03 12:30:52 发布