《数据结构与算法分析——C语言描述》 第九章
#include"hash.h"
#include"graph.h"
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
#include"fatal.h"
#include<stack>
#include<float.h>
#include<queue>
#define MAXN 10000
char nameRecord[MAXN][100];
int vexNum = 0;//点的个数计数器
Graph g1;//原来的图
Graph g2;//倒过来的的图
void readGraph() {
HashTable hash_StrToNum = initializeTable_hash(5);//初始化一个哈希表
g1 = initialize_Graph(5);//初始化一个邻接图
g2 = initialize_Graph(5);
char i_name[100];
char j_name[100];
int i, j;//点i,点
double weight;//权
while (scanf("%s%s%lf", i_name, j_name, &weight) == 3) {//输入两个点的名字,和他们之间的权,成功读入的话进入循环
if (!isExist(i_name, hash_StrToNum)) {//查看曾经是否输入了点i,在O(1)内迅速找出
//点i第一次出现
i = vexNum;//给点i分配图的下标
strcpy(nameRecord[vexNum], i_name);//复制到名字记录中
hash_StrToNum = insert_hash(i_name, vexNum, hash_StrToNum);//插入到哈希表中,O(1)完成
vexNum++;//计数器增加
}
else {
//以前出现过点i
i = map_hash(i_name, hash_StrToNum);//O(1)内迅速获取点i的下标
}
if (!isExist(j_name, hash_StrToNum)) {
j = vexNum;
strcpy(nameRecord[vexNum], j_name);
hash_StrToNum = insert_hash(j_name, vexNum, hash_StrToNum);
vexNum++;
}
else {
j = map_hash(j_name, hash_StrToNum);
}
insertEdge(i, j, weight, g1);//在图中插入边
insertEdge(j, i, weight, g2);//反过来插入到另一个图中,关键路径的时候要倒过来
}
destroyTable_hash(hash_StrToNum);
}
void printGraph(Graph g) {
if (g) {
for (int i = 0; i < vexNum; i++) {//给所有点来一个遍历
EdgeNodePtr p = getEdgeNodePtr(i, g);//获取邻接的点
printf("indegree:%d ", indegree(i, g));
while (p) {
printf("(%s,%s)%g ", nameRecord[i], nameRecord[getVex(p)], getWeight(p));
p = advance(p);//获取下一个节点
printf("\n");
}
}
}
else {
Error("EMPTY GRAPH");
}
}
struct TableEntry {
double ec;
double lc;
};
typedef struct TableEntry* Table;//数组
Table t;
std::stack<int> topsort() {
int counter = 0;
Vertex v, w;
std::queue<int> q;
int *indegree = indegreeArray(g1, vexNum);
std::stack<int> topNumStack;
for (int i = 0; i < vexNum; i++) {
t[i].ec = 0;
}
for (int i = 0; i < vexNum; i++) {
if (indegree[i] == 0)
q.push(i);
}
while (!q.empty()) {
v = q.front();
q.pop();
topNumStack.push(counter++);
EdgeNodePtr adjVexptr = getEdgeNodePtr(v, g1);
while (adjVexptr) {
w = getVex(adjVexptr);
indegree[w]--;
if (indegree[w] == 0) {
q.push(w);
}
if (t[v].ec + getWeight(adjVexptr)>t[w].ec) {
t[w].ec = t[v].ec + getWeight(adjVexptr);
}
adjVexptr = advance(adjVexptr);
}
}
if (counter != vexNum) {
Error("has cycle");
}
return topNumStack;
}
void criticalPath() {
std::stack<int> topStack= topsort();
for (int i = 0; i < vexNum; i++) {
t[i].lc = t[topStack.top()].ec;
}
while (!topStack.empty()) {
Vertex v = topStack.top();
topStack.pop();
EdgeNodePtr adjVexptr = getEdgeNodePtr(v, g2);
while (adjVexptr) {
Vertex w = getVex(adjVexptr);
if (t[v].lc - getWeight(adjVexptr) < t[w].lc) {
t[w].lc = t[v].lc - getWeight(adjVexptr);
}
adjVexptr = advance(adjVexptr);
}
}
for (int i = 0; i < vexNum; i++) {
if (t[i].ec == t[i].lc)
printf("%s\n", nameRecord[i]);
}
}
int main() {
freopen("filein.txt", "r", stdin);
readGraph();
t = (Table)malloc(sizeof(struct TableEntry)*vexNum);
criticalPath();
}