1. 程式人生 > >ALDS1_11_B Depth First Search

ALDS1_11_B Depth First Search

ALDS1_11_B Depth First Search

題目:
https://cn.vjudge.net/problem/Aizu-ALDS1_11_B

程式碼如下:

#include<bits/stdc++.h>
using namespace std;
#define MAX 105
#define WHITE 0
#define GREY 1
#define BLACK 2

int a[MAX][MAX],s[MAX],f[MAX],color[MAX],n,tt;

void dfs_visit(int u)
{
    int v;
    color[u] = GREY;
    s[u] = ++tt;
    for(int v = 0;v < n;v++)
    {
        if(a[u][v] == 0) continue;
        if(color[v] == WHITE) dfs_visit(v);
    }
    color[u] = BLACK;
    f[u] = ++tt;
}

void dfs()
{
    int u;
    for(u = 0;u < n;u++) color[u] = WHITE;
    tt = 0;
    for(u = 0;u < n;u++)
    {
        if(color[u] == WHITE) dfs_visit(u);
    }
}

int main()
{
    int u,k,v;
    scanf("%d",&n);
    for(int i = 0;i < n;i++)
    {
        scanf("%d%d",&u,&k);
        u--;
        for(int i = 0;i < k;i++)
        {
            scanf("%d",&v);
            v--;
            a[u][v] = 1;
        }
    }
    dfs();
    for(int i = 0;i < n;i++) cout << i + 1 << " " << s[i] << " " << f[i] << endl;
    return 0;
}

這道題考察的是DFS,先來介紹一下DFS演算法,實現DFS可以使用棧也可以使用遞迴,這裡本人使用遞迴的方式來完成這項操作的。首先,以鄰接矩陣的形式來輸入,先把所有的結點都標記為白色(白色代表的就是還沒有訪問過的結點),隨後從最初的結點向後訪問,並且將已經訪問的結點標記為灰色(灰色代表這個結點已經被訪問,而且這個被訪問的結點可能還有通往其他未訪問結點的可能)。當一個結點已經將所有的結點都訪問過後就將該結點標記為黑色(黑色代表這個結點已經沒有訪問其他新的結點的可能了)。其實通俗來說DFS就是先訪問一個結點然後一直深入下去,知道沒路可走了,再返回上一個結點,檢視是否還有其他路徑可走,如果有則再一路向前,如果沒有就返回上個結點依次類推,直到所有的結點都被訪問。
這裡題目還要求記錄每個結點的第一次被訪問的時間,和訪問完這個節點的時間,所以需要設定一個全域性變數tt,每次訪問一個新的結點都選將tt加1,並且賦給新結點的開始時間,每次當一個結點訪問完成後都需要將此時的時間賦給這個結點的結束時間。