1. 程式人生 > >算法導論22.3深度優先搜索 練習總結 (轉載)

算法導論22.3深度優先搜索 練習總結 (轉載)

由於 .net -c art 單個 hit 包含 strong 進行

22.3-1 畫一個 3*3 的網格,行和列的擡頭分別標記為白色、灰色和黑色,對於每個表單元 (i, j),請指出對有向圖進行深度優先搜索的過程中,是否可能存在一條邊,鏈接一個顏色為 i 的結點和一個顏色為 j 的結點。對於每種可能的邊,指明該種邊的類型。另外,請針對無向圖的深度優先搜索再制作一張這樣的網格。

ANSWER:技術分享

22.3-2 給出深度優先搜索算法在圖 22-6 上的運行過程。假定深度優先搜索算法的第 5~7 行的 for 循環是以字母表順序依次處理每個結點,假定每條鄰接鏈表皆以字母表順序對立面的結點進行了排序。請給出每個結點的發信啊時間和完成時間,並給出每條邊的分類。

ANSWER:技術分享

22.3-3 給出圖 22-4 的深度優先搜索的括號化結構。

ANSWER:技術分享

22.3-4 證明:使用單個位來存放每個結點的顏色已經足夠。這一點可以通過證明如下事實來得到:如果將 DFS-VISIT 的第 8 行刪除,DFS 給出的結果相同。

ANSWER:和 22.2-3 類似,事實上,在 DFS-VISIT 中,在遞歸過程中,系統會調用棧存放未被檢測的結點,並不一定需要將結點著黑色和灰色來區別,因為程序中並沒有檢測結點是否黑色的命令。著黑白灰是為了易於觀察。

22.3-5 證明邊 (u, v) 是:

a. 樹邊或前向邊當且僅當 u.d < v.d < v.f < u.f。

b. 後向邊當且僅當 v.d ≤ u.d < u.f ≤ v.f。

c. 橫向邊當且僅當 v.d < v.f < u.d < u.f。

ANSWER:由於深度優先搜索滿足括號化結構,將結點的關系以括號化結構表示易證明此關系。

22.3-6 證明:在無向圖中,根據深度優先搜索算法是先搜索 (u, v) 還是先搜索 (v, u) 來將邊 (u, v) 分類為樹邊或者後向邊,與根據分類列表中的 4 種類型的次序進行分類是等價的。

ANSWER:有向圖是將無向圖的一條邊變成有方向的兩條邊。所以本質上分類標準是等價的。

22.3-7 請重寫 DFS 算法的偽代碼,以便使用棧來消除遞歸調用。

ANSWER:

DFS-VISIT:
    STACK.push(u)
    while ! STACK.empty
        u = STACK.top
        if u.color == GRAY
            u.color = BLACK
            time = time + 1
            u.f = time
            STACK.pop
            continue
        if u.color == WHITE
            u.color = GRAY
            time = time + 1
            u.d = time
        for each v ∈ G:Adj[u]
            v.π = u
            STACK.push(u)

22.3-8 請給出如下猜想的一個反例:如果有向圖 G 包含一條從結點 u 到結點 v 的路徑,並且在對圖 G 進行深度優先搜索時有 u.d < v.d,則結點 v 是結點 u 在深度優先森林中的一個後代。

ANSWER:技術分享

22.3-9 請給出如下猜想的一個反例:如果有向圖 G 包含一條從結點 u 到結點 v 的路徑,則任何對圖 G 的深度優先搜索都將導致 v.d ≤ u.f。

ANSWER:和 22.3-8 反例的圖一樣。

技術分享

22.3-10 修改深度優先搜索的偽代碼,讓其打印出有向圖 G 的每條邊及其分類。並指出,如果圖 G 是無向圖, 要進行何種修改才能達到相同的效果。

ANSWER:在完成 DFS 之後對有向圖 G 的邊進行遍歷,按照 22.3-5的結論的規則。

技術分享
CLASSIFY-EDGE(G):
    for each vertex u ∈ G.V
        for each v ∈ G:Adj[u]
            if v.π == u:
                edge(u, v).c = T
            else if u.d < v.d < v.f < u.f :
                edge(u, v).c = F
            else if v.d ≤ u.d < u.f ≤ v.f:
                edge(u, v).c = B
            else:
                edge(u, v).c = C
View Code

無向圖:只需要把三個 else 改成一個 else,分類為後向邊即可。

22.3-11 請解釋有向圖的一個結點 u 怎樣才能成為深度優先樹中的唯一結點,即使結點 u 同時有入邊和出邊。

ANSWER:

技術分享

22.3-12 證明:我們可以在無向圖 F 上使用深度優先搜索來獲得圖 G 的連通分量,並且深度優先森林所包含的數的棵數與 G 的連通分量數量相同。更準確地說,請給出如何修改深度優先搜索來讓其每個結點賦予一個介於 1 和 k 之間的整數值 v.cc,這裏 k 是 G 的連通分量數,使得 u.cc = v.cc 當且僅當結點 u 和結點 v 處於同一個連通分量中。

ANSWER:當執行 DFS 的第 5、6 行時,每跳入一次第 7 行,連通分量數加 1,在 DFS-VISIT 裏遇到的結點的聯通分量數相同。

聯通分支的數量用ceil表示,代碼修改如下

技術分享
void Link_Graph::DFS()
{
    int u, ceil = 0;
    //對每個頂點初始化
    for(u = 1; u <= n; u++)
    {
        V[u].color = WHITE;
        V[u].p =  NULL;
    }
    //時間戳初始化
    time = 0;
    //依次檢索V中的頂點,發現白色頂點時,調用DFS_Visit訪問該頂點
    for(u = 1; u <= n; u++)
    {
        if(V[u].color == WHITE)
        {
            ceil++;
            DFS_Visit(u, ceil);
        }
    }
}

void Link_Graph::DFS_Visit(int u, int ceil)
{
    int v;
    Edge *e;
    //將u置為灰色
    V[u].color = GRAY;
    //使全局變量time增值
    time++;
    //將time的新值記錄為發現時間
    V[u].d = time;
    e = V[u].head;
    while(e)
    {
        v = e->end;
        //如果頂點為白色
        if(V[v].color == WHITE)
        {
            //遞歸訪問頂點
            V[v].p = u;
            DFS_Visit(v, ceil);
            //樹邊
            e->type = TREE;
        }
        else if(V[v].color == GRAY)
        {
            //反向邊
            e->type = BACK;
        }
        else if(V[v].color == BLACK)
        {
            //正向邊
            if(V[u].d < V[v].d)
                e->type = FORWARD;
            //交叉邊
            else
                e->type = CROSS;
        }
        e = e->next;
    }
    //以u為起點的所有邊都被探尋後,置u為黑色
    V[u].color = BLACK;
    V[u].ceil = ceil;
    //並將完成時間記錄在f[u]中
    time++;
    V[u].f = time;
}
View Code

*22.3-13 對於有向圖 G = (V, E) 來說,如果 u ~ v 以為這圖 G 至多包含一條從 u 到 v 的簡單路徑,則圖 G 是單連通圖。請給出一個有效算法來判斷一個有向圖是否單連通圖。

ANSWER:

單連通圖沒有正向邊(向前邊)

算法導論22.3深度優先搜索 練習總結 (轉載)