关键路径求解
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网:
每个节点的最早发生时间[圆框对应的内容]和最迟发生时间[方框对应的内容]:
程序运行结果: