• 图的深度优先搜索dfs


     图的深度优先搜索:

    1.将最初访问的顶点压入栈;

    2.只要栈中仍有顶点,就循环进行下述操作:

    (1)访问栈顶部的顶点u;

    (2)从当前访问的顶点u 移动至顶点v 时,将v 压入栈。如果当前顶点u 不存在未访问的相邻矩阵,则将u 从栈中删除;

     

    主要的几个变量:

    color[n]用WHITE、GRAY、BLACK 中的一个来表示顶点i 的访问状态
    M[n][n]邻接矩阵, 如果存在顶点i 到顶点j 的边,则M[i][j]为true
    Stack S

    栈, 暂存访问过程中的顶点

    其中color 数组中, 白色代表“未访问的顶点”, 灰色代表“访问过的顶点”(虽然被访问过了,但仍然可能留有通往未访问顶点的边), 黑色代表”访问结束的顶点”;

     

    有俩种方法实现深度优先遍历

    (1)用递归实现的深度优先搜索

    #include<stdio.h>
    
    #define N 100
    #define WHITE 0
    #define GRAY 1
    #define BLACK 2
     
    int n, M[N][N];
    int color[N], d[N], f[N], tt;//color[n]表示该顶点访问与否,d[n]表示该顶点的发现时刻 ,f[n]表示该顶点的结束时刻 ,tt表示时间 
    
    
    //用递归函数实现的深度优先搜索 
    void dfs_visit(int u) {
        int v;
        color[u] = GRAY;
        d[u] = ++tt;
        for(v = 0; v < n; v++) {
            if(M[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; 
        
        //以未访问的u为起点进行深度优先搜索
        for(u = 0; u < n; u++) {
            if(color[u] == WHITE)
                dfs_visit(u);
        } 
        
        //输出 
        for(u = 0; u < n; u++) {
            printf("%d %d %d
    ", u+1, d[u], f[u]); 
        }
    }
    
    int main() {
        int u, v, k, i, j;
        
        scanf("%d", &n);
        //初始化 
        for(i = 0; i < n; i++) {
            for(j = 0; j < n; j++) {
                M[i][j] = 0;
            }
        }
        //输入数据,构造邻接矩阵 
        for(i = 0; i < n; i++) {
            scanf("%d %d", &u, &k);
            u--;
            for(j = 0; j < k; j++) {
                scanf("%d", &v);
                v--;
                M[u][v] = 1;
            }
        }
        
        dfs();
        
        return 0;
    }
    
    /*
    6
    1 2 2 3
    2 2 3 4 
    3 1 5
    4 1 6
    5 1 6
    6 0
    */

    (2)用栈实现的深度优先搜索

    #include<iostream>
    #include<stack> 
    using namespace std;
    
    static const int N = 100; 
    static const int WHITE = 0;
    static const int GRAY = 1;
    static const int BLACK = 2;
    
    int n, M[N][N];
    int color[N], d[N], f[N], tt;//color[n]表示该顶点访问与否,d[n]表示该顶点的发现时刻 ,f[n]表示该顶点的结束时刻 
    int nt[N];//记录每个顶点的邻接顶点偏移量,eg:顶点0有俩个顶点1,2;现已经访问过1了,那么, nt[u] = 1; 下次直接访问2 
    
    //按编号顺序获取与u相邻的v
    int next(int u) {
        for(int v = nt[u]; v < n; v++) {
            nt[u] = v + 1;
            if(M[u][v])    return v;
        }
        return -1;
    }
    
    
    void dfs_visit(int r) {
        for(int i = 0; i < n; i++)    nt[i] = 0;
        
        stack <int> S;
        S.push(r);
        color[r] = GRAY;
        d[r] = ++tt;
        
        while( !S.empty() ) {
            int u = S.top();
            int v = next(u);
            if(v != -1) {
                if(color[v] == WHITE) {
                    color[v] = GRAY;
                    d[v] = ++tt;
                    S.push(v);
                }
            }
            else {
                S.pop();
                color[u] = BLACK;
                f[u] = ++tt;
            }
        }
    }
    
    void dfs() {
        //初始化
        for( int i = 0; i < n; i++) {
            color[i] = WHITE;
            nt[i] = 0;
        } 
        //设置时间 
        tt = 0;
        
        //以未访问的u为起点进行深度优先搜索,设置循环的目的应该是防止该图不是连通图 
        for(int u = 0; u < n; u++) {
            if(color[u] == WHITE)    dfs_visit(u);
        }
        
        for(int i = 0; i < n; i++) {
            cout << i+1 << " " << d[i] << " " << f[i] << endl;
        }
    }
    
    int main() {
        int u, k, v;
        cin >> n; //顶点数 
         
        //邻接矩阵置零 
        for( int i = 0; i < n; i++) {
            for(int j = 0; j < n; j++) 
                M[i][j] = 0;
        }
        
        //创建邻接矩阵 
        for(int i = 0; i < n; i++) {
            cin >> u >> k;//输入顶点和顶点的度
            u--;
            for(int j = 0; j < k; j++) {
                cin >> v;
                v--;
                M[u][v] = 1;
            } 
        }
        
        dfs();
        
        return 0;
    }
    
    /*
    6
    1 2 2 3
    2 2 3 4 
    3 1 5
    4 1 6
    5 1 6
    6 0
    */ 
  • 相关阅读:
    函数Sort()
    数据窗口中数值型对象的显示格式
    函数IsValid()
    20130109显示器无反应
    DropDownPictureListBox设置默认项
    大数据
    字符串函数Mid()
    Jquery获取当前元素所在表格的行列数
    关于模式窗口中treeView问题
    格式化字符串长度 超出指定长度用....代替
  • 原文地址:https://www.cnblogs.com/mr-wei977955490/p/15367602.html
Copyright © 2020-2023  润新知