兩種方式判斷有向圖是否有環-python實現

1. DFS判斷有向圖是否有環

假設圖以鄰接矩陣表示,一條深度遍歷路線中如果有結點被第二次訪問到,那麼有環。我們用一個變量來標記某結點的訪問狀態(未訪問,訪問過,其後結點都被訪問過),然後判斷每一個結點的深度遍歷路線即可。

def dfs(G,i,color):
    r = len(G)
    color[i] = -1
    have_circle = 0
    for j in range(r):	# 遍歷當前節點i的所有鄰居節點
        if G[i][j] != 0:
            if color[j] == -1:
                have_circle = 1
            elif color[j] == 0:
                have_circle = dfs(G,j,color)
    color[i] = 1
    return have_circle

def findcircle(G):
    # color = 0 該節點暫未訪問
    # color = -1 該節點訪問了一次
    # color = 1 該節點的所有孩子節點都已訪問,就不會再對它做DFS了
    r = len(G)
    color = [0] * r
    have_circle = 1
    for i in range(r):	# 遍歷所有的節點
        if color[i] == 0:
            have_circle = dfs(G,i,color)
            if have_circle == 0:
                break
    return have_circle

G = [[0,1,0],[0,0,1],[1,0,0]]  #這裏的1說明行index對應的節點指向列index對應的節點,對角線處爲0
# G = [[0,0,0,1,0],[1,0,0,0,0],[0,0,0,1,1],[0,0,0,0,0],[0,1,0,0,0]]
have_circle = findcircle(G)
print(have_circle)

2. 拓撲排序判斷環

拓撲排序方法是重複尋找一個入度爲0的頂點,將該頂點從圖中刪除(即放進一個隊列裏存着,這個隊列的順序就是最後的拓撲排序),並將該結點及其所有的出邊從圖中刪除(即該結點指向的結點的入度減1,因爲下面代碼中有入度的都爲1,所以直接賦值爲0 即可),最終若圖中全爲入度爲1的點,則這些點至少組成一個迴路,或者最後的隊列中節點個數不爲中的個數,也說明有環。

def findcircle(G):
    node_set = set()
    r = len(G)
    have_in_zero = True
    while have_in_zero:
        have_in_zero = False
        for i in range(r):
            if i not in node_set and not any([row[i] for row in G]):
                node_set.add(i)
                G[i] = [0] * r
                have_in_zero = True
                break
    return False if len(node_set)==r else True


G = [[0,1,0],[0,0,1],[1,0,0]]
# G = [[0,0,0,1,0],[1,0,0,0,0],[0,0,0,1,1],[0,0,0,0,0],[0,1,0,0,0]]
have_circle = findcircle(G)
print(have_circle)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章