• 深夜敲模板_4——无向图的割顶和桥


    /***
        dfs遍历一遍整个图,标出时间戳 dfs_clock,保存在pre[]里
        遍历后得到一个森林
        对于每一颗树,每个节点是割顶的情况:
            1:根:    有两个或两个以上的子节点
            2:非根:  对于节点u,low(u)表示u及u的所有节点的反向边所能连回的最早的节点的pre[]值
                       如果u的所有子节点的low[v]>=pre[u]; 那么u节点就是割顶
                       特别的,如果low[u]>pre[u],边(u,v)还是一个桥
        初始化是,假设所有的low(u)=u;即所有节点都能连回自己
    ***/
    1:
    int head[MAXN],pre[MAXN],low[MAXN],cnt,dfs_clock;
    bool iscut[MAXN],isedgecut[MAXM];///true表示是割顶
    struct Edge{
        int v;
        int next,to;
    }edge[MAXM>>1];
    
    void add(int u,int v){
        edge[cnt].to = v;
        edge[cnt].next = head[u];
        head[u] = cnt++;
    }
    
    void init(){
        cnt = dfs_clock = 0;
        memset(head,-1,sizeof(head));
        memset(pre,0,sizeof(pre));
    }
    
    void dfs(int u,int fa){
        low[u] = pre[u] = ++dfs_clock;
        int child = 0;
        *****int lowv  = dfs_clock+1;
        for(int i = head[u];i != -1;i = edge[i].next){
            int v = edge[u].to;
            if(!pre[v]){
                child++;
                dfs(v,u);
                *****lowv = min(lowv,low[v]);
                low[u] = min(low[u],low[v]);
                if(low[v] >= pre[u])    iscut[u] = true;///这个地方也可以改成vector,找的时候更快
                *****if(low[v] > pre[u])     isedgecut[i] = true;///找到的桥
            }
            else if(v != fa && pre[v] < pre[u]){
                low[u] = min(low[u],pre[v]);
            }
        }
        if(fa == -1 && child > 1)   iscut[u]=true;
        *****if(fa == -1 && lowv != u){
            for(int i = head[u];i != -1;i = edge[i].next)  isedgecut[i]=true;
        }
    }
    
    2:
    vector <int> G[MAXN];
    *****vector < pair<int,int> > edge;
    
    void dfs(int u,int fa){
        low[u] = pre[u] = ++dfs_clock;
        int child = 0;
        *****int lowv  = dfs_clock+1;
        for(int i = 0;i < G[u].size();i++){
            int v = G[u][v];
            if(!pre[v]){
                child++;
                dfs(v,u);
                *****lowv = min(lowv,low[v]);
                low[u] = min(low[u],low[v]);
                if(low[v] >= pre[u])    iscut[u] = true;
                *****if(low[v] > pre[u])    edge.push_back(mak_pair(u,v));
            }
            else if(v != fa && pre[v] < pre[u]){
                low[u] = min(low[u],pre[v]);
            }
        }
        if(fa == -1 && child > 1)   iscut[u] = true;
        *****if(fa == -1 && lowv != u){
            for(int i = 0;i < G[u].size();i++)  edge.push_back(make_pair(u,v));
        }
    }
    

  • 相关阅读:
    java常用类-----String类的源码分析、可变和不可变序列
    java常用类-----包装类及自动装箱和拆箱
    java数组---------二分查找_折半检索
    java数组------冒泡排序和优化
    java数组--------多维数组及数组存储表格数据
    java数组------Arrays工具类使用
    Volley超时重试机制
    Volley框架原理
    模块化实现(好处,原因)
    Android系统显示原理
  • 原文地址:https://www.cnblogs.com/hqwhqwhq/p/4555881.html
Copyright © 2020-2023  润新知