http://blog.csdn.net/hackerain/article/details/6054188
01.#include <iostream>
02.using namespace std;
03.#define MAX 10000000
04.#define MAX_VERTEX_NUM 20
05.int ve[MAX_VERTEX_NUM];
06./*顺序栈的定义*/
07.#define Stack_Size 100
08.typedef struct sqStack
09.{
10. int *elem;
11. int top;
12. int stackSize;//栈数组长度
13.}sqStack;
14.
15.
16./*顺序栈的初始化*/
17.void initStack_Sq(sqStack &S)
18.{
19. S.elem=new int[Stack_Size];
20. S.top=-1;
21. S.stackSize=Stack_Size;
22.}
23./*入栈*/
24.void push(sqStack &S,int x)
25.{
26. if(S.top==Stack_Size-1)
27. cout<<"Stack Overflow!";
28. S.elem[++S.top]=x;
29.}
30.
31./*出栈*/
32.int pop(sqStack &S)
33.{
34. int x;
35. if(S.top==-1)
36. cout<<"Stack Empty!";
37. x=S.elem[S.top--];
38. return x;
39.}
40.typedef struct EdgeNode
41.{//边表结点的定义
42. int adjvex;//存放邻接点在顶点表中的位置
43. struct EdgeNode * nextedge;//指向下一个边表结点
44. int weight;
45.}EdgeNode;
46.typedef struct VexNode
47.{//顶点表结点的定义
48. char vex;//存放顶点信息
49. EdgeNode * firstedge;//指向第一个边表结点
50. int indegree;
51.}VexNode;
52.typedef struct
53.{//顶点表的定义
54. VexNode vexs[MAX_VERTEX_NUM];
55. int vexnum,edgenum;
56.}LGraph;
57./*构造有向图的邻接表*/
58.void CreateDG_AL(LGraph &G,int n,int e)
59.{
60. int i,j,k,w;
61. G.vexnum=n;
62. G.edgenum=e;
63. for(i=0;i<n;i++)
64. {
65. cin>>G.vexs[i].vex;
66. G.vexs[i].firstedge=NULL;//初始化为空
67. }
68. for(k=0;k<e;k++)
69. {
70. EdgeNode *p;
71. cin>>i>>j>>w;
72. p=new EdgeNode;
73. p->adjvex=j;
74. p->weight=w;
75. p->nextedge=G.vexs[i].firstedge;
76. G.vexs[i].firstedge=p;//采用头插法
77. }
78.}
79.//拓扑排序并求各顶点事件的最早发生时间及拓扑逆序列
80.void TopoSort(LGraph &G,sqStack &T)
81.{
82. sqStack S;
83. initStack_Sq(S);
84. EdgeNode *p;
85.
86. int count=0;
87. int i;
88. for(i=0;i<G.vexnum;i++)
89. G.vexs[i].indegree=0;//初始化为0
90. for(i=0;i<G.vexnum;i++)
91. {//计算各个顶点的入度
92. p=G.vexs[i].firstedge;
93. while(p)
94. {
95. G.vexs[p->adjvex].indegree++;
96. p=p->nextedge;
97. }
98. }
99. for(i=0;i<G.vexnum;i++)
100. if(G.vexs[i].indegree==0)
101. push(S,i);//将度为0的顶点入栈,这里进栈的是入度为0的顶点在数组中的位置
102. for(i=0;i<G.vexnum;i++)
103. ve[i]=0;//初始化顶点事件的最早发生时间为0
104. while(S.top!=-1)
105. {
106. i=pop(S);
107. cout<<G.vexs[i].vex<<" ";//将栈顶的元素出栈且输出,即将入度为0的顶点输出
108. push(T,i);//为了求得拓扑序列的逆序列,将元素依次进栈就得到了逆序列
109. count++;//计数器加1
110. p=G.vexs[i].firstedge;//让p指向入度为0的顶点的第一个边表结点
111. while(p)
112. {
113. int k;
114. int dut;
115. dut=p->weight;
116. k=p->adjvex;
117. G.vexs[k].indegree--;//将入度为0的顶点的邻接点的入度减1
118. if(G.vexs[k].indegree==0)
119. push(S,k);//度减1后的顶点如果其入度为0,则将其入栈
120. if(ve[i]+dut>ve[k])
121. ve[k]=ve[i]+dut;//经过while循环,将顶点事件的所有邻接点的最早发生时间算出来,
122. //并且经过外层的while循环,不断地更新为较大的ve[k]值
123. p=p->nextedge;
124. }
125. }
126. cout<<endl;
127. if(count<G.vexnum)
128. cout<<"Network G has citcuits!"<<endl;
129.}
130.//求关键路径和关键活动
131.void CriticalPath(LGraph &G)
132.{
133. int i,j,k,dut;
134. int ee,el;
135. int vl[MAX_VERTEX_NUM];
136. EdgeNode *p;
137. sqStack T;
138. initStack_Sq(T);
139. TopoSort(G,T);
140. for(i=0;i<G.vexnum;i++)
141. vl[i]=ve[G.vexnum-1];//初始化顶点事件的最迟发生时间为汇点的最早发生时间
142. //因为求最迟发生时间是从汇点向源点开始计算的
143. while(T.top!=-1)
144. {//经过while循环,按堆栈顺序求出每个顶点的最迟发生时间
145. for(j=pop(T),p=G.vexs[j].firstedge; p ;p=p->nextedge)
146. {//这里应该注意for循环的机制:每一次循环都要判断一次条件,包括第一次
147. k=p->adjvex;
148. dut=p->weight;
149. if(vl[k]-dut<vl[j])
150. vl[j]=vl[k]-dut;//按堆栈T中事件的顺序,将该顶点事件的最迟发生时间经过for循环算出来,
151. //注意:经过for循环算出的是一个顶点的最迟发生时间
152. }
153. }
154. for(i=0;i<G.vexnum;i++)
155. {//依次遍历每一个活动
156. for(p=G.vexs[i].firstedge;p;p=p->nextedge)
157. {
158. k=p->adjvex;
159. dut=p->weight;
160. ee=ve[i];//求活动的最早开始时间
161. el=vl[k]-dut;//求活动的最迟开始时间
162. if(ee==el)
163. {//若两者相等,说明这这个活动为关键活动
164. cout<<"("<<G.vexs[i].vex<<","<<G.vexs[k].vex<<")"<<dut<<" ";
165. cout<<"ee="<<ee<<","<<"el="<<el<<endl;
166. }
167. }
168. }
169.}
170.void main()
171.{
172. freopen("in.txt","r",stdin);
173. LGraph G;
174. CreateDG_AL(G,9,11);
175. CriticalPath(G);
176.}
求关键路径的关键如下:
1、每个顶点所代表的事件的最早和最迟发生时间
2、每条弧所代表的活动的最早和最迟开始时间
事件的最早发生时间:ve[源点]=0,ve[k]=MAX{ve[j]+dut(<j,k>)},即在k前面的事件的最早发生时间加上那些事件到k所需要的时间所得的值中取最大值。
事件的最迟发生时间:vl[汇点]=ve[汇点],vl[j]=MIN{vl[k]-dut(<j,k>)},即在j后面的事件的最迟发生时间减去j到那些事件所需的时间所得的值中取最小值。
活动的最早开始时间:ee[i]=ve[j],即该项活动最早开始时间与该项活动的开始事件的最早时间相同
活动的最迟开始时间:el[i]=vl[k]-dut(<j,k>),即活动的最迟开始时间等于该项活动的结束事件的最迟发生时间减去该项活动持续的时间。
代码如下:
#include <stack>
using namespace std;
#define MAX 1000000
#define MAX_VERTEX_NUM 20
int ve[MAX_VERTEX_NUM];
typedef struct EdgeNode
{
int adjvex;
struct EdgeNode* nextedge;
int weight;
}EdgeNode;
typedef struct VexNode
{
char vex;
EdgeNode* firstedge;
int indegree;
}VexNode;
typedef struct
{
VexNode vexs[MAX_VERTEX_NUM];
int vexnum,edgenum;
}LGraph;
void CreateDG_AL(LGraph &G,int n,int e)
{
int i,j,k,w;
G.vexnum=n;
G.edgenum=e;
for(i=0;i<n;i++)
{
cin>>G.vexs[i].vex;
G.vexs[i].firstedge=NULL;
}
for(k=0;k<e;k++)
{
EdgeNode* p;
cin>>i>>j>>w;
p=new EdgeNode;
p->adjvex=j;
p->weight=w;
p->nextedge=G.vexs[i].firstedge;
G.vexs[i].firstedge=p;
}
}
//拓扑排序并求出各个顶点事件的最早发生时间以及逆拓扑排序
void TopoSort(LGraph &G,std::stack<int>& T)
{
std::stack<int> S;
EdgeNode* p;
int count=0;
int i;
for(i=0;i<G.vexnum;i++)
G.vexs[i].indegree=0;//初始化为0
for(i=0;i<G.vexnum;i++)
{//计算各个顶点的入度
p=G.vexs[i].firstedge;
while(p)
{
G.vexs[p->adjvex].indegree++;
p=p->nextedge;
}
}
for(i=0;i<G.vexnum;i++)
if(G.vexs[i].indegree==0)
S.push(i);
for(i=0;i<G.vexnum;i++)
ve[i]=0;//初始化顶点事件的最早发生时间为0
while(!S.empty())
{
i=S.top();
S.pop();
cout<<G.vexs[i].vex<<" ";
T.push(i);
count++;
p=G.vexs[i].firstedge;
while(p)
{
int k;
int dut;
dut=p->weight;
k=p->adjvex;
G.vexs[k].indegree--;
if(G.vexs[k].indegree==0)
S.push(k);
if(ve[i]+dut>ve[k])
ve[k]=ve[i]+dut;
p=p->nextedge;
}
}
cout<<endl;
if(count<G.vexnum)
cout<<"Network G has citcuits!"<<endl;
}
//求关键路径和关键活动
void CriticalPath(LGraph &G)
{
int i,j,k,dut;
int ee,el;
int vl[MAX_VERTEX_NUM];
EdgeNode* p;
std::stack<int> T;
TopoSort(G,T);
for(i=0;i<G.vexnum;i++)
vl[i]=ve[G.vexnum-1];
while(!T.empty())
{
j=T.top();
T.pop();
for(p=G.vexs[j].firstedge;p;p=p->nextedge)
{
k=p->adjvex;
dut=p->weight;
if(vl[k]-dut<vl[j])
vl[j]=vl[k]-dut;
}
}
for(i=0;i<G.vexnum;i++)
{
for(p=G.vexs[i].firstedge;p;p=p->nextedge)
{
k=p->adjvex;
dut=p->weight;
ee=ve[i];
el=vl[k]-dut;
if(ee==el)
{
cout<<"("<<G.vexs[i].vex<<","<<G.vexs[k].vex<<")"<<dut<<" ";
cout<<"ee="<<ee<<","<<"el="<<el<<endl;
}
}
}
}
int main()
{
LGraph G;
CreateDG_AL(G,9,11);
CriticalPath(G);
return 0;
}