「關鍵路徑尋找」問題——C語言實現

題目:關鍵路徑尋找

對於給定的一個工程施工圖,該圖以邊爲單位從鍵盤輸入,編寫可以找出該圖的關鍵路徑的程序。

完整代碼

#include<stdio.h>
#include<stdlib.h>

typedef struct Node{
    int vex;
    int dut; //持續時間
    struct Node *next;
}Node;

typedef struct Hnode{
    int index; //入度 
    int data;
    Node *out;
}Hnode;

int ve[100]; //最晚發生時間 
int vl[100]; //最先發生時間
int stackS[100]; //入度爲0的頂點序列棧
int stackT[100]; //逆拓撲序列棧
int topS = -1, topT = -1;

int TopoSort(Hnode A[], int m){
    int i, j, k, count = 0;
    Node *p;

    for(i=1; i<=m; i++){
        ve[i] = 0;//初始化最先發生時間 
        if( A[i].index==0 ){
            topS++;
            stackS[topS] = i;
        }
    }

    while ( topS!=-1 ){
        j = stackS[topS];
        topS--;
        topT++;
        stackT[topT] = j;
        count++;
        
        p = A[j].out;
        while (p!=NULL)
        {
            k = p->vex;
            A[k].index--;
            if( A[k].index==0 ){
                topS++;
                stackS[topS] = k;
            }
            if (ve[j] + p->dut > ve[k])
                ve[k] = ve[j] + p->dut;
            p = p->next;
        }
    }
    if( count<m ) return 0;
    else return 1;
}

int CriticalPath(Hnode A[], int m){
    int i, j, k, dut, ei, li;
    Node *p;
    if( !TopoSort(A, m) ){
        printf("* 工程圖中存在環,無關鍵路徑。\n");
        return 0;
    }
    for(i=1;i<=m;i++)
        vl[i] = ve[m]; //始化爲最先發生時間
    while( topT!=-1 ){
        j = stackT[topT];
        topT--; //按逆拓撲順序求各頂點的vl
        p = A[j].out;
        while( p!=NULL){
            k = p->vex;
            if( vl[k] - p->dut < vl[j] )
                vl[j] = vl[k] - p->dut;
            p = p->next; 
        }
    }
    
    printf("* 關鍵路徑(標記爲'*')以下:\n\n");
    for(j=1;j<=m;j++){
        p = A[j].out;
        while( p!=NULL ){
            k = p->vex;
            dut = p->dut;
            ei = ve[j];
            li = vl[k] - dut;
            if( ei==li )
                printf("* <%d, %d>: dut=%d, e(i)=%d, l(i)=%d\n", A[j].data, A[k].data, dut, ei, li);
            else printf("  <%d, %d>: dut=%d, e(i)=%d, l(i)=%d\n", A[j].data, A[k].data, dut, ei, li);
            p = p->next;
        }
    }
}

void main(){
    int m, n, i;
    printf("* 請輸入頂點個數:");
    scanf("%d",&m);
    printf("* 請輸入邊的條數:");
    scanf("%d",&n);
    Hnode A[m+1];

    for(i=1;i<=m;i++){
        A[i].index = 0;
        A[i].data = i;
        A[i].out = NULL;
    }
    
    int u, v, w;
    Node *p;
    printf("* 請輸入%d條邊以及該邊的權:\n", n);
    for(i=0;i<n;i++){
        scanf("%d%d%d",&u,&v,&w);//讀入各邊以及邊的權值
        p = (Node*)malloc( sizeof(Node) );
        A[v].index++;
        p->vex = v;
        p->dut = w;
        p->next = A[u].out;
        A[u].out = p;
    }
    CriticalPath(A, m);
}

參考資料

西北大學MOOC:拓撲排序
西北大學MOOC:關鍵路徑node

相關文章
相關標籤/搜索