[ZZ]如何判斷有向圖是否成環

 

如何判斷有向圖是否成環

原文鏈接:http://blog.csdn.net/nomad2/archive/2007/04/10/1559664.aspx

(1)如何判斷一個圖是不是含有環?

a. DFS,出現返回邊則有環。

b. 拓撲排序,若所有的頂點都出現在拓撲排序中,則不出現環。

(2)拓撲排序

a.什麼是偏序,全序?from:

http://www.programfan.com/club/showbbs.asp?id=221968

偏序是由實數中的>=和<=抽象出來的
在一個集合F中定義一個比較關係, 這個關係不要求任意兩個元素都能比較
這個關係可以任意定義,記爲< , 但是定義的關係要滿足以下3個條件
1) 任意a屬於F,有a < a;               ...說明元素自己可以和自己比較
2) 如果a和b能比較 且a < b, b和c能比較,且 b < c
   那麼a和c就能比較,且a < c          ...說明比較關係具有傳遞性
3) 如果a和b能比較,且a < b, b < a, 那麼a = b 
定義的這種滿足以上3條公理的比較關係就叫偏序,和所在的集合記爲( F, < )

全序首先是偏序,但是比偏序多一個要求:集合中的任意兩個元素都是可比的。

b.拓撲排序:

由偏序定義得到拓撲有序的操作便是拓撲排序(topological order)。

算法:

(1) 在有向圖中選一個沒有前驅的頂點輸出。

(2) 從圖中刪除該定點和所有以它爲尾的弧。

(3) 重複前兩步,直至所有節點都輸出,或當前圖中不存在無前驅的節點(存在環)。

圖採用鄰接表實現,頭文件代碼如下:

#define MAX_VERTEX_NUM 20

typedef int InfoType;
typedef char VertexType;

typedef enum {DG, DN, UDG, UDN} GraphKind;

typedef struct ArcNode{
    int adjvex;
    struct ArcNode *next;
    InfoType info;
}
ArcNode;

typedef struct VNode{
    int in_degree;
    VertexType data;
    ArcNode *firstarc;
}
VNode, AdjList[MAX_VERTEX_NUM];

typedef struct {
    AdjList vertex;
    int vexnum, arcnum;
    GraphKind kind;
}
algraph;

源文件代碼:

#include "algraph_topo.h"

#include "stdio.h"
#include "stdlib.h"

void createDN(algraph &g){}
void createUDN(algraph &g){}
void createUDG(algraph &g){}

//locate the name vertice's index
int locate(algraph g, char name){
    for(int i = 0; i < g.vexnum; i++){
        if(name == g.vertex[i].data){
            return i;
        }

    }

    return -1;
}


void createDG(algraph &g){
    printf("input the number of vertex and arcs: ");
    scanf("%d %d", &g.vexnum, &g.arcnum);
    fflush(stdin);
    
    int i = 0, j = 0, k = 0;
    
    printf("input the name of vertex: ");
    
    for(i = 0; i < g.vexnum; i++){
        scanf("%c", &g.vertex[i].data);
        fflush(stdin);
        g.vertex[i].firstarc = NULL;
        g.vertex[i].in_degree = 0;
    }

    
    //construct the adjacent list
    char v1, v2;
    int w;
    ArcNode *p;

    printf("input the %d arcs v1 v2 and weight: ", g.arcnum);
    for(k = 0; k < g.arcnum; k++){
        scanf("%c %c %d", &v1, &v2, &w);
        fflush(stdin);
        i = locate(g, v1);
        j = locate(g, v2);

        //new a node
        p = (ArcNode *)malloc(sizeof(ArcNode));
        p->adjvex = j;
        p->info = w;
        p->next = NULL;

        //insert the node in the head of list
        if(!g.vertex[i].firstarc){
            g.vertex[i].firstarc = p;
        }
else{
            p->next = g.vertex[i].firstarc;
            g.vertex[i].firstarc = p;
        }


        g.vertex[j].in_degree++;
    }

}


//print the list
void printGraph(algraph g){
    for(int i = 0; i < g.vexnum; i++){
        printf("%c's adjacent list is: ", g.vertex[i].data);
        ArcNode *p = g.vertex[i].firstarc;
        while(p){
            printf("%c(%d) ", g.vertex[p->adjvex].data, p->info);
            p = p->next;
        }

        printf(" ");
    }

}


void createGragh(algraph &g){
    
    printf("please input the type of graph: ");
    scanf("%d", &g.kind);
    
    switch(g.kind){
    case DG: 
        createDG(g);
        //printGraph(g);
        break;
    case DN: 
        createDN(g);
        break;
    case UDG: 
        createUDG(g);
        break;
    case UDN: 
        createUDN(g);
        break;
    }

}


//²éÕÒÏÂÒ»¸ö
int findNext(algraph g){
    for(int i = 0; i < g.vexnum; i++){
        if(g.vertex[i].in_degree == 0){
            return i;
        }

    }

    return -1;
}


//topo order
void topoSort(algraph g){
    printf("the topo sort of graph is: ");
    for(int i = 0; i < g.vexnum; i++){
        int index = findNext(g);
        if(index > -1){
            printf("%c ", g.vertex[index].data);

            //don't consider the vertice again
            g.vertex[index].in_degree = -1;
            
            ArcNode *p = g.vertex[index].firstarc;
            while(p){
                g.vertex[p->adjvex].in_degree--;
                p = p->next;
            }

        }
else{
            break;
        }

    }

    printf(" ");
}


void main(){
    algraph g;
    createGragh(g);
    topoSort(g);
}

程序的運行結果如下:

please input the type of graph:
0
input the number of vertex and arcs:
6 8
input the name of vertex:
a
b
c
d
e
f
input the 8 arcs v1 v2 and weight:
a d 1
a c 1
a b 1
c e 1
c b 1
d e 1
f e 1
f d 1
the topo sort of graph is:
a       c       b       f       d       e
Press any key to continue

說明:

(1) 爲了避免重複檢測入度爲0的頂點,可設置一個棧暫存所有入度爲0的頂點,複雜度爲O(n + e)。而在程序中採用的是

    //don't consider the vertice again
    g.vertex[index].in_degree = -1;

來實現的。複雜度要高一些。

(2) 可以使用DFS,退出DFS函數的順序即爲逆向的拓撲有序序列。

(3)關鍵路徑 

a. AOV網:用頂點表示活動,用弧表示活動間的優先關係的有向圖稱爲頂點表示活動的網(activity on vertex network)。AOV網中,沒有有向環。

b. AOE網:邊表示活動的網絡(頂點表示事件,弧表示活動),用來估算工程的完成時間,通常只有一個源點和一個匯點。

c. 求AOE算法的複雜度是O(n + e)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章