6)图[4]关键路径

关键路径求解

  1 #include "iostream"
  2 #include "vector"
  3 #include "stack"
  4 using namespace std;
  5 
  6 const int MaxNumVertex  = 20; //最大顶点数
  7 const int infinity = 65535;//无穷大
  8 typedef int elementtype;       //elementtype 为int 型
  9 class graph{
 10 public:
 11     graph();
 12     ~graph();
 13     elementtype insertvertex(elementtype v); //在图中增加一个顶点
 14     elementtype insertedge(elementtype v,elementtype u,elementtype weight);//在图中增加一条从v顶点到u顶点的弧
 15     elementtype firstadj(elementtype v);//求图g中顶点v的第一个邻接点
 16     elementtype nextadj(elementtype v,elementtype m);//求图中顶点v的m邻接点之后的邻接点
 17     elementtype firstpre(elementtype v);//求图中顶点v的第一个前驱
 18     elementtype nextpre(elementtype v,elementtype m);//求图中顶点v的m前驱点之后的前驱点
 19     elementtype degreein(elementtype v);//求图中顶点v的入度数
 20     elementtype FindDegreein(elementtype ind[]);//各顶点的入度存放于入度数组中
 21     elementtype degreeout(elementtype v);//求图中顶点v的入度数
 22     elementtype FindDegreeout(elementtype oud[]);//各顶点的入度存放于入度数组中
 23     elementtype EW(elementtype E[]);//最早发生时间的求解
 24     bool CriticalPath();//关键路径
 25     elementtype create();//创建图
 26     int  CurrentVertex;//当前顶点数
 27 
 28 private:
 29     elementtype vertex[MaxNumVertex];//顶点表
 30     elementtype edge[MaxNumVertex][MaxNumVertex];//图中弧的类型
 31     
 32 };
 33 
 34 /*
 35 *初始化
 36 */
 37 graph::graph()
 38 {
 39     CurrentVertex = 0; 
 40     int i,j;
 41     for (i=MaxNumVertex-1;i>=1;i--)
 42     {
 43         for (j=MaxNumVertex-1;j>=1;j--)
 44         {
 45             edge[i][j] = 0;
 46 
 47         }
 48     }
 49     
 50 }
 51 
 52 /*
 53 *在图中增加一个顶点
 54 */
 55 elementtype graph::insertvertex(elementtype v)
 56 {
 57     //判断这个顶点是否已经存在
 58     int i;
 59     bool flags = true;
 60     for(i=1; i<=CurrentVertex; i++)
 61     {
 62         if(vertex[i]==v)
 63         {
 64             flags = false;
 65             break;
 66         }
 67     }
 68     
 69     if(flags)
 70     {
 71         CurrentVertex++;
 72         vertex[CurrentVertex] = v;
 73     }else{
 74         cout<<v<<"顶点已经存在!"<<endl;
 75     }
 76     return 0;
 77 }
 78 
 79 /*
 80 *在图中增加一条从v顶点到u顶点的弧
 81 */
 82 elementtype graph::insertedge(elementtype v,elementtype u,elementtype weight)
 83 {
 84     if(edge[v][u]!=0)
 85     {
 86         cout<<v<<"->"<<u<<"这条弧弧已经存在!"<<endl;
 87     }else{
 88         edge[v][u] = weight;
 89     }
 90     return 0;
 91 }
 92 
 93 
 94 /*
 95 *求图中顶点v的第一个邻接点
 96 */
 97 elementtype graph::firstadj(elementtype v)
 98 {
 99     int u,i;
100     bool flags = true;//用于判断是否存在邻接点
101     for(i=1;i<=CurrentVertex;i++)
102     {
103         if(edge[v][i]!=0){
104             u = i;
105             flags = false;
106             break;
107         }
108     }
109     if(flags) u = 0;//邻接点不存在
110     return u;
111 }
112 
113 /*
114 *求图中顶点v的m邻接点以后的邻接点
115 */
116 elementtype graph::nextadj(elementtype v,elementtype m)
117 {
118     int i,u;
119     bool flags = true;
120     for(i=m+1;i<=CurrentVertex;i++)
121     {
122         if(edge[v][i]!=0)
123         {
124             u = i;
125             flags = false;
126             break;
127         }
128     }
129     if(flags) u = 0;//邻接点不存在
130     return u;
131 }
132 
133 /*
134 *求图中顶点v的第一个前驱
135 */
136 elementtype graph::firstpre(elementtype v)
137 {
138     int u,i;
139     bool flags = true;//用于判断是否存在邻接点
140     for(i=1;i<=CurrentVertex;i++)
141     {
142         if(edge[i][v]!=0){
143             u = i;
144             flags = false;
145             break;
146         }
147     }
148     if(flags) u = 0;//前驱点不存在
149     return u;
150 }
151 
152 /*
153 *求图中顶点v的m前驱点之后的前驱点
154 */
155 elementtype graph::nextpre(elementtype v,elementtype m)
156 {
157     int i,u;
158     bool flags = true;
159     for(i=m+1;i<=CurrentVertex;i++)
160     {
161         if(edge[i][v]!=0)
162         {
163             u = i;
164             flags = false;
165             break;
166         }
167     }
168     if(flags) u = 0;//前驱点不存在
169     return u;
170 }
171 /*
172 *求图中顶点v的入度数
173 */
174 elementtype graph::degreein(elementtype v)
175 {
176     int i,num = 0;
177     for (i=1;i<=CurrentVertex;i++)
178     {
179         if(edge[i][v]!=0)num++;
180     }
181     return num;
182 }
183 
184 /*
185 *每个顶点的入度
186 */
187 elementtype graph::FindDegreein(elementtype ind[])
188 {
189     int i;
190     for(i=1;i<=CurrentVertex;i++)
191     {
192         ind[i] = degreein(i);
193     }
194     return 0;
195 }
196 
197 /*
198 *求图中顶点v的出度数
199 */
200 elementtype graph::degreeout(elementtype v)
201 {
202     int i,num = 0;
203     for (i=1;i<=CurrentVertex;i++)
204     {
205         if(edge[v][i]!=0)num++;
206     }
207     return num;
208 }
209 
210 /*
211 *每个顶点的出度
212 */
213 elementtype graph::FindDegreeout(elementtype outd[])
214 {
215     int i;
216     for(i=1;i<=CurrentVertex;i++)
217     {
218         outd[i] = degreeout(i);
219     }
220     return 0;
221 }
222 
223 
224 /*
225 *最早发生时间的求解
226 */
227 elementtype graph::EW(elementtype E[])
228 {
229     int i,x,w,v;
230     stack<int> s;//定义并初始索要用到的栈
231     elementtype ind[MaxNumVertex];//求各顶点的入度存放于入度数组ind中
232     FindDegreein(ind);//
233 
234     for(i=1;i<=CurrentVertex;i++)//各个结点最早发生时间的初始化
235     {
236         E[i] = -1;
237     }
238 
239     
240     for(i=1;i<=CurrentVertex;i++)//将入度为0的顶点入栈
241     {
242         if(ind[i]==0)
243         {
244             s.push(i);
245             v = i;
246             E[i] = 0;//第一个入度为0的结点的最早发生时间为0
247         }
248     }
249     int count =0;//用于统计已经完成的结点数目
250     while(!s.empty())
251     {
252         x = s.top();
253         count++;//计数
254         s.pop();
255         w = firstadj(x);//开始对v的各个后继顶点的入度-1
256         while(w!=0)
257         {
258             if(E[w]<(E[x]+edge[x][w]))
259             {
260                 E[w] = E[x]+edge[x][w];//更新w的最早发生时间
261             }
262             if(!(--ind[w]))//若w的入度-1后为0,则入栈
263             {
264                 s.push(w);
265             }
266             w = nextadj(x,w);
267         }
268     }
269     if(count<CurrentVertex)return false;//产生有回路的标志
270     else return true;
271     return 0;
272 }
273 
274 /*
275 *关键路径
276 */
277 bool graph::CriticalPath()
278 {
279     int i,x,w,v;
280     stack<int> s;//定义并初始索要用到的栈
281     elementtype ind[MaxNumVertex];//求各顶点的入度存放于入度数组ind中
282     elementtype outd[MaxNumVertex];//求各顶点的出度存放于出度数组outd中
283     elementtype E[MaxNumVertex];
284     elementtype L[MaxNumVertex];
285     FindDegreein(ind);//求各个结点的入度
286     FindDegreeout(outd);//求各个结点的出度
287     EW(E);//求各个结点的最早发生时间
288     
289     for(i=1;i<=CurrentVertex;i++)
290     {
291         L[i] = infinity;//各个结点最迟发生时间的初始化
292     }
293     for(i=1;i<=CurrentVertex;i++)//将出度为0的顶点入栈
294     {
295         if(outd[i]==0)
296         {
297             s.push(i);
298             v = i;
299             L[i] = E[i];//第一个出度为0的结点的最迟发生时间
300         }
301     }
302     int count =0;//用于统计已经完成的结点数目
303     while(!s.empty())
304     {
305         x = s.top();
306         count++;//计数
307         s.pop();
308         w = firstpre(x);//开始对v的各个前驱顶点的出度-1
309         while(w!=0)
310         {
311             if(L[w]>(L[x]-edge[w][x]))
312             {
313                 L[w] = L[x]-edge[w][x];//更新w结点的最迟发生时间
314             }
315             if(!(--outd[w]))//若w的出度-1后为0,则入栈
316             {
317                 s.push(w);
318             }
319             w = nextpre(x,w);
320         }
321 
322     }
323 
324     cout<<"E[i],L[i]:"<<endl;
325     for(i=1;i<=CurrentVertex;i++)//输出各个节点的最早发生时间和最迟发生时间
326     {
327         cout<<"E["<<i<<"]="<<E[i]<<",L["<<i<<"]="<<L[i]<<endl;
328     }
329     cout<<endl;
330 
331     vector<int>equal;//记录E[I]=L[I]
332     for(i=1;i<=CurrentVertex;i++)
333     {
334         if(E[i]==L[i])
335         {
336             equal.push_back(i);
337         }
338     }
339 
340     int start,end;
341     for(i=1;i<=CurrentVertex;i++)//寻找起始结点
342     {
343         if(ind[i]==0)
344         {
345             start = i;
346             break;
347         }
348     }
349     FindDegreeout(outd);//求各个结点的出度
350     for(i=CurrentVertex;i>=1;i--)//寻找终止结点
351     {
352         if(outd[i]==0)
353         {
354             end = i;
355             break;
356         }
357     }
358 
359     cout<<"CriticalPath is:";
360     while(start!=end)
361     {
362         for(i=0;i<equal.size();i++)//输出关键路径
363         {
364             if(edge[start][equal[i]]!=0)
365             {
366                 cout<<start<<"->";
367                 start = equal[i];
368                 if(start==end)
369                 {
370                     cout<<start<<endl;
371                 }
372                 break;
373             }
374         }
375     }
376     return 0;
377 }
378 
379 /*
380 *创建图
381 */
382 elementtype graph::create()
383 {
384     int i,numv,v,u,weight;
385     cout<<"please create graph"<<endl;
386     cout<<"input numvertex(顶点数):";
387     cin>>numv;
388     cout<<"input vertex(顶点):";
389     for(i=1;i<=numv;i++)
390     {
391         cin>>v;
392         insertvertex(v);
393     }
394     cout<<"input num(u,v,weight)(弧的数目):";
395     cin>>numv;
396     for(i=1;i<=numv;i++)
397     {
398         cout<<"u->v,weight:";
399         cin>>u>>v>>weight;
400         insertedge(u,v,weight);
401     }
402     cout<<"graph create finish!"<<endl<<endl;
403     return 0;
404 }
405 graph::~graph()
406 {
407 }
408 
409 int main()
410 {
411     graph g;
412     g.create();
413     g.CriticalPath();
414     return 0;
415 }

原始AOV网:

每个节点的最早发生时间[圆框对应的内容]和最迟发生时间[方框对应的内容]:

程序运行结果:

原文地址:https://www.cnblogs.com/minmsy/p/5012579.html