圖的關節點:
如果刪去某個節點及依附在該節點上的邊后,該圖被分割為兩個或兩個以上的連通圖,則該節點為關節點。
計算關節點的關鍵思路:
在該圖的深度優先生成樹上,如果某個節點的孩子節點(不一定是二叉樹,孩子節點可能大於2)的子樹中,所有孩子節點的子樹中都有回邊能回到該節點的祖先上,則該節點不是關鍵節點,因為即使刪除了該節點,該節點的祖先或它的孩子都能通過回邊將彼此連結起來。與之對應,如果該節點的孩子節點中,但凡有一個孩子節點的子樹中沒有回邊,則該節點一定為關鍵節點,因為即使其他的孩子節點都有回邊,但刪除該節點后,這個沒有回邊的孩子節點還是與被刪節點的祖先間分割開了。
一點不是問題的問題:
對於當前節點v,在不考慮v是整個樹的根節點的情況下,v只有在它的某一個子樹w中,w及w的子節點里不存在到v的父母或祖先節點的回邊的情況下,v才是關鍵節點(只有在v的所有的孩子節點的子樹上都有回邊才不算關鍵點,P177中,G5的B只有在C上才有回邊,因此B仍然為關鍵節點)。
現在對low(v):
Low(v)在visited[v],low[w],visited[k]中找最小值,w為v的孩子節點,k為與v有回邊的父母或祖先節點。
首先看vistited[v],對visited[v]來說,它是v的被訪問順序,由於訪問時使用的前序遍歷,因此越靠近葉子節點的節點visited值越大。
再看low[w],low[w]是用於統計v的孩子節點的回邊的情況的,現在加入v沒有回邊回到它的祖先的回邊,但如果它的子節點w有或w的子節點里有,則等價於v也有了這個回邊,因為v可以通過w來訪問到v的祖先。
對於visited[k],這個用於統計v到祖先的回邊。
Low(v)的過程,實際上就是比較visited[v],low[w],visited[k]的大小,如果low[w]最小,說明v的子節點w的子樹中有回邊到v的祖先,如果visited[k]最小,說明v有到v的祖先的回邊。
計算得到的low(v),是用於判斷v的父親節點是否為關鍵節點的,因為low(v)是v所能到達的最淺的節點,它要么是它被訪問的順序(visited[v]),要么是通過子樹回邊到達的最淺節點(low(w)),要么是通過自己的回邊到達的最淺節點(visited[k])。
對一個節點,當它的孩子節點的最淺節點小於它的被訪問順序,也就是low[w]<visited[v]時,說明v的孩子節點中有回邊繞過了v到達了v的祖先。如果v的所有孩子節點都有這樣的回邊,則刪除v后祖先節點一樣能通過回邊訪問到v的孩子,而不影響連通性。
而如果只要有一個孩子節點使low[w]>=visited[v],也就是代表該孩子節點無法繞過v,則v就是關鍵節點,因為祖先節點無法繞過v訪問這個孩子。