#include <iostream>
#include <string.h>
#include <stack>
#include <cstdio>
using namespace std;
typedef string element;
struct ArcNode
{ //边结点
int weight;
int adjuex;
ArcNode *nextarc;
};
struct VNode
{ //顶点结点
element data;
ArcNode *firstarc;
};
class Graph
{
private:
VNode *vertex;
int vernum, arcnum;
public:
Graph(int vernum, int arcnum)
{
this->vernum = vernum;
this->arcnum = arcnum;
vertex = new VNode[vernum];
for (int i = 0; i < vernum; i++)
{
vertex[i].firstarc = NULL;
}
}
int connected(element e)
{
for (int i = 0; i < vernum; i++)
{
if (e == vertex[i].data)
{
return i;
}
}
cout << "没有该顶点" << endl;
return -1;
}
void cinCreate()
{
cout << "输入" << vernum << "个顶点" << endl;
for (int i = 0; i < vernum; i++)
{
cin >> vertex[i].data;
}
cout << "输入" << arcnum << "条边" << endl;
element v1, v2;
int n1, n2;
for (int i = 0; i < arcnum; i++)
{
cin >> v1 >> v2;
n1 = connected(v1);
n2 = connected(v2);
ArcNode *p = new ArcNode;
p->adjuex = n2;
cin >> p->weight;
p->nextarc = vertex[n1].firstarc;
vertex[n1].firstarc = p;
}
}
void show()
{
for (int i = 0; i < vernum; i++)
{
ArcNode *p = vertex[i].firstarc;
while (p)
{
cout << "<" << vertex[i].data << ", " << vertex[p->adjuex].data << ">"
<< " : " << p->weight << endl;
p = p->nextarc;
}
}
}
void topoSort(int *arr)
{
stack<int> s;
int i;
//初始化indegree数组
int *indegree = new int[vernum];
for (int i = 0; i < vernum; i++)
{
indegree[i] = 0;
}
for (i = 0; i < vernum; i++)
{
ArcNode *p = vertex[i].firstarc;
while (p)
{
indegree[p->adjuex]++;
p = p->nextarc;
}
}
//入度为0的点入栈
for (i = 0; i < vernum; i++)
{
if (!indegree[i])
{
s.push(i);
}
}
//其他为0点入栈
for (i = 0; i < vernum; i++)
{
arr[i] = s.top();
s.pop();
ArcNode *p = vertex[arr[i]].firstarc;
while (p)
{
if (!--indegree[p->adjuex])
{
s.push(p->adjuex);
}
p = p->nextarc;
}
}
}
void shortPath()
{
int i;
//调用拓扑排序 排列顺序
int *topolist = new int[vernum];
topoSort(topolist);
//最早发生时间ve
int *ve = new int[vernum];
memset(ve, 0, vernum * sizeof(int)); //初始化,int型只能初始化为0或-1
for (int i = 0; i < vernum; i++)
{ //遍历所有结点
int k = topolist[i]; //依次取出拓扑序列
ArcNode *p = vertex[k].firstarc; // p指向k的邻接点
while (p)
{ //邻接点存在
int j = p->adjuex; //邻接点的位置(下标)
//在所有最早的时间中找到一个最迟的,(等待最迟的完成)代表该点的最早
if (ve[j] < ve[k] + p->weight)
{ //若k的最早时间 加 k到j 的时间 比j 的最早时间迟,存上最长时间(因为j点要等待它前面所有点完成,即时间最长的完成)
ve[j] = ve[k] + p->weight; // ve[j]存上最早时间
}
p = p->nextarc;
}
}
//最晚发生时间vl
int *vl = new int[vernum];
for (i = 0; i < vernum; i++)
{ //初始化为汇点的最早时间
vl[i] = ve[vernum - 1];
}
for (i = vernum - 1; i >= 0; i--)
{
int k = topolist[i];
ArcNode *p = vertex[k].firstarc;
while (p)
{
int j = p->adjuex; //邻接点
if (vl[k] > vl[j] - p->weight)
{ //若j最迟时间 减 k到j的时间 比 k的最迟时间早,存最早(在所有最迟时间中找到一个最早的作为最迟时间,以保证所有的都不会迟到)
vl[k] = vl[j] - p->weight;
}
p = p->nextarc;
}
}
//判断某活动是否为关键活动
for (i = 0; i < vernum; i++)
{
ArcNode *p = vertex[i].firstarc;
while (p)
{
int j = p->adjuex; //邻接点
int e = ve[i]; //最早活动
int l = vl[j] - p->weight; //(最迟活动)邻接点最迟时间 减 i到j的时间
if (e == l)
{ //相等则为关键路径
cout << "<" << vertex[i].data << ", " << vertex[j].data << ">" << ends;
}
p = p->nextarc;
}
}
cout << endl;
}
};
int main()
{
int n, e;
freopen("input.txt", "r", stdin);
cin >> n >> e;
Graph g(n, e);
g.cinCreate();
g.show();
g.shortPath();
return 0;
}
input.txt
9 11
v0 v1 v2 v3 v4 v5 v6 v7 v8
v0 v1 6
v0 v2 4
v0 v3 5
v1 v4 1
v2 v4 1
v3 v5 2
v4 v6 9
v4 v7 7
v5 v7 4
v6 v8 2
v7 v8 4