关键路径

问题:

一项工程有n个小项目要完成,一些项目的开始建立在一些项目的完成的基础上。求哪些项目是关键项目?
(关键项目:提前该项目可以缩短工程时间)
 
关键项目求解:
》对邻接表进行拓扑排序。
》按拓扑排序的顺序求每个项目完成的最早时间。
》按逆拓扑序列求每个项目完成的最迟时间。
》其中 最迟时间==最早时间 的项目就是 ‘关键项目’。
#include <stack>
#include <memory>
#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

#define MAX  1000//定义图结点的最大个数
int n, m;        //n代表顶点数,m代表边数
int ve[MAX], vl[MAX]; //记录事件的最早发生,最迟发生时间

typedef struct arc_data //边信息
{
    int time;
    int vex;       //邻接的结点在数组中的编号
    struct arc_data *next;
} arc_data;

struct Node    //顶点信息
{
    arc_data *head;
} adj[MAX];

bool v[MAX]= {false};
int in_count[MAX]; //记录结点入度数的数组
int topo[MAX];    //保存拓扑排序结果
void create( )  //生成图(邻接表实现)
{
    int i;
    memset(in_count, 0, sizeof(int)*(n+1));   //入度数组清零
    for(i=1; i<=n; ++i)  //初始化表头结点
        adj[i].head = NULL;
    for(i=0; i<m; i++)
    {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        in_count[b]++;    // 记录入度值
        arc_data *q;
        q = new arc_data;
        q->time=c;
        q->vex = b;
        q->next= adj[a].head;  //新边插入邻接表~~
        adj[a].head = q;
    }
}

bool topo_sort() //邻接表拓扑排序
{
    stack<int> S;
    arc_data *p ;
    int showNum=0, k=1;   //记录输出的结点的数目
    for(int i=1; i<=n; ++i)//在in_count数组中找出入度为0的结点,并分别入栈
        if(in_count[i]==0)
            S.push(i);     //入度为0的全入栈
    while(!S.empty())
    {

        int v=S.top();
        S.pop();
        topo[k++]=v;     //记录拓扑排序结果
        in_count[v]=-1; //将该点入度调为-1
        ++showNum;
        p=adj[v].head;
        while(p!=NULL) //遍历以v为起点所临接的点
        {
            --in_count[p->vex];        //结点入度数减1
            if(in_count[p->vex]==0)   //入度数为0时入栈
                S.push(p->vex);
            p=p->next;
        }
    }
    if(showNum<n) return 0; //存在环
    return 1;
}

bool  import_path(){
    if(!topo_sort()) return 0;
    /****   获取最早发生时间  ****/
    memset(ve, 0, sizeof(ve)); // 将每个时间最早发生时间初始为0
    for(int i=1; i<=n; i++){
        int k=topo[i];      //拓扑排序第一个序号开始
        arc_data *p = adj[k].head;  //p指向第一个邻接顶点
        while(p!=NULL){              //更新k的关联的顶点的最早发生时间
int j=p->vex;           //j为邻接点信号
            if(ve[j] < ve[k]+p->time) //跟新j的最早发生时间
                ve[j]=ve[k]+p->time;
            p = p->next;
        }
    }
    /**** 最迟发生时间  ****/
    for(int i=1; i<=n; i++)   //将每个事件最迟发生时间ve[n]
        vl[i]=ve[n];
    for(int i=n; i>0; i--){
        int k=topo[i];
        arc_data *p=adj[k].head;
        while(p!=NULL){
            int j=p->vex;
            if(vl[k] > vl[j]-p->time){
vl[k]
=vl[j]-p->time;        }
p
=p->next; } } return 1; } void print(){ /**** 判断每个事件是不是关键事件 ****/ for(int i=1; i<=n; i++){ int k=topo[i]; arc_data *p=adj[k].head; while(p!=NULL){ int j=p->vex; if(ve[k] == (vl[j]-p->time) ){
printf(
"%d->%d是关键路径\n", k, j);
       } p
=p->next; } } return ; } int main(){ while(scanf("%d%d", &n, &m)!=EOF){ create(); if(import_path()){
       print();      }
}
return 0; }

 

 

posted @ 2015-09-22 15:21  马晨  阅读(104)  评论(0)    收藏  举报