问题描述:一个工程上的关键活动直接影响着整个工程的进展情况,要求实现关键路径上问题的求解。
例图:
输入示例:
//9 11
//V1 V2 V3 V4 V5 V6 V7 V8 V9
//a3 1 4 5 a2 1 3 4 a1 1 2 6 a4 2 5 1 a5 3 5 1 a6 4 6 2 a8 5 8 7 a7 5 7 9 a9 6 9 4 a10 7 9 2 a11 8 9 4
存储结构(邻接表):
typedef struct ArcNode {
string arcName; //弧的名称
int adjvex; //弧的邻接点位置
struct ArcNode *nextarc; //指向下一条弧的指针
InfoType info; //弧长
int ee;//活动最早开始时间
int el;//活动最晚开始时间
}ArcNode;
typedef struct VNode {
VertexType vName; //顶点名称
ArcNode *firstarc; //指向第一条依附该顶点的弧的指针
}Vnode;
typedef struct {
VNode vertices[MAX_VERTEX_NUM];//顶点数组
int vexnum, arcnum; //图的当前顶点数和弧数
}ALGraph;
求拓扑序列函数:
Status TopologicalOrder(ALGraph G, stack<int> &T) {
//求各事件的最早发生时间ve
//T为拓扑序列顶点栈,S为零入度顶点栈
//若G无回路,则用栈T返回G的一个拓扑序列,且函数返回值为OK,否则为ERROR
//对各顶点求入度indegree[0..vernum-1]
FindInDegree(G, indegree);
stack<int> S;//建立零点入度栈S
for (int i = 0; i < G.vexnum; i++)
if (!indegree[i])
S.push(i);
//工程起始点入栈
int count = 0;
for (int i = 0; i < G.vexnum; i++)
ve[i] = 0;//事件最早发生时间初始化
while (!S.empty()) {
//入度为零的点最先输出,并将其所有邻接点入度减一,更新事件最早发生时间
int j = S.top();
S.pop();
T.push(j);
++count;
for (ArcNode *p = G.vertices[j].firstarc; p; p = p->nextarc) {
int k = p->adjvex;
if (--indegree[k] == 0)
S.push(k);
//若入度减为0,则入栈
if (ve[j] + p->info > ve[k])
ve[k] = ve[j] + p->info;
//p->info=dut(<j,k>)
}
}
if (count < G.vexnum) {
return ERROR;
}
else
return OK;
}
求关键路径函数:
Status CriticalPath(ALGraph G) {
//若图中有回路,程序结束
stack<int> T;
if (!TopologicalOrder(G, T)) {
cout << "有回路!" << endl;
return ERROR;
}
//初始化顶点事件最迟发生时间
for (int i = 0; i < G.vexnum; i++)
vl[i] = ve[G.vexnum-1];
//按拓扑逆序列求各顶点的vl值
while (!T.empty()) {
int j = T.top();
T.pop();
for (ArcNode *p = G.vertices[j].firstarc; p; p = p->nextarc){
int k = p->adjvex;
int dut = p->info;
if (vl[k] - dut < vl[j])
vl[j] = vl[k] - dut;
}
}
//遍历所有的边,求出活动发生的最早时间和最晚时间
for (int j = 0; j < G.vexnum; j++)
for (ArcNode *p = G.vertices[j].firstarc; p; p = p->nextarc) {
int k = p->adjvex;
int dut = p->info;
p->ee = ve[j];
p->el = vl[k] - dut;
}
return OK;
}
求入度函数:
void FindInDegree(ALGraph G,int *indegree){
for (int i = 0; i < G.vexnum; i++)
indegree[i] = 0;
for (int j = 0; j < G.vexnum; j++)
for (ArcNode *p = G.vertices[j].firstarc; p; p = p->nextarc)//遍历所有的边
++indegree[p->adjvex];//边的邻接点的度加一
}
图的创建函数:
void CreateGraph(ALGraph &G) {
cout << "------------------请输入顶点个数,活动个数:-------------------" << endl;
cin >> G.vexnum >> G.arcnum;
cout << "-------------------请输入" << G.vexnum << "个顶点的名称:----------------------" << endl;
for (int i = 0; i < G.vexnum; i++) {
cin >> G.vertices[i].vName;
G.vertices[i].firstarc = NULL;
}
int startPoint, terminalPoint;//边的起点和终点
cout << "-------请输入" << G.arcnum << "条边的名称,起始点编号,终止点编号,权值:--------" << endl;
for (int j = 0; j < G.arcnum; j++) {
ArcNode *p = NULL;//边结点初始化
int length;//边的权值
string arcname;
cin >> arcname >> startPoint >> terminalPoint >> length;
if(startPoint<1 || startPoint>G.vexnum || terminalPoint<1 || terminalPoint>G.vexnum) {
cout << "!输入超出顶点编号范围!请重新输入:" << endl;
exit(0);
}
startPoint--;//减一后变为下标
terminalPoint--;
p = new ArcNode;
if (!p) {
cout << "申请空间失败!" << endl;
exit(0);
}
p->arcName = arcname;
p->info = length;
p->adjvex = terminalPoint;
//倒插法,输入各顶点的邻接边时倒序输入
p->nextarc = G.vertices[startPoint].firstarc;
G.vertices[startPoint].firstarc = p;
}
cout << "----------------------------输入完成-------------------------" << endl << endl;
}
图的销毁函数:
void DestroyGraph(ALGraph &G) {
ArcNode *p,*q;
for (int i = 0; i < G.vexnum; i++) {
p = G.vertices[i].firstarc;
while (p) {
q = p;
p = p->nextarc;
free(q);
}
}
G.arcnum = 0;
G.vexnum = 0;
}
输出函数:
void PrintGraph(ALGraph G) {
cout << endl;
cout << " 结果 " << endl;
cout << "--------------------------------------------------------------" << endl;
cout << setw(6) << "顶点" << setw(6) << "ve" << setw(6) << "vl" << endl;
cout << "--------------------------------------------------------------" << endl;
for (int i = 0; i < G.vexnum; i++) {
cout << setw(6) << G.vertices[i].vName;
cout << setw(6) << ve[i];
cout << setw(6) << vl[i];
cout << endl;
}
cout << "--------------------------------------------------------------" << endl;
cout << setw(6) << "活动" << setw(13) << "起始点" << setw(6) << "时间" << setw(6) << "e" << setw(6) << "l" << setw(10) << "关键活动" << endl;
cout << "--------------------------------------------------------------" << endl;
for (int j = 0; j < G.vexnum; j++)
for (ArcNode *p = G.vertices[j].firstarc; p; p = p->nextarc) {
int k = p->adjvex;
cout << setw(6) << p->arcName;
cout << setw(6) << G.vertices[j].vName << "---->" << G.vertices[k].vName;
cout << setw(6) << p->info;
cout << setw(6) << p->ee;
cout << setw(6) << p->el;
//如果活动最早发生时间等于最晚发生时间,则其为关键活动
int flag = (p->ee == p->el) ? 1 : 0;
if (flag)
cout << setw(10) << "是" << endl;
else
cout << setw(10) << "否" << endl;
}
cout << "--------------------------------------------------------------" << endl;
}
运行结果: