zoukankan      html  css  js  c++  java
  • 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网:

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

    程序运行结果:

  • 相关阅读:
    1>/dev/null 2>&1的含义
    rpm常用命令及rpm参数介绍
    linux按位运算
    关于比较运算符的一个例子
    js屏蔽效果
    jquery异步提交无刷新
    常用js验证
    获取输入字符的首字母(中文为拼音首字母)
    SQL查询合并字符串
    获取鼠标点击的坐标处理
  • 原文地址:https://www.cnblogs.com/minmsy/p/5012579.html
Copyright © 2011-2022 走看看