zoukankan      html  css  js  c++  java
  • Tarjan [割点, 缩点, 桥(待填坑)]

    • 割点

    删除这个点后, 图的联通块数量变多.

    DFSDFS 时, 设当前点为 kk, low[]low[] 为最高祖先, dfn[]dfn[]dfsdfs 序, totokk 直接相连的点,

    • toto 点被访问过, 则说明 kk 有向上的边, low[k]=min(low[k],dfn[to])low[k]=min(low[k], dfn[to])

    • 否则沿着 toto 继续递归, 回溯时 low[k]=min(low[k],low[to])low[k] = min(low[k], low[to]),

      low[to]low[to]kk 下方, 说明切掉kk, toto 会在下方形成一个独立的环,

      1. kk 不为根节点, kk割点 ,
      2. kk 为根节点, 必须有两个以上儿子才算是割点 .
    void Tarjan(int k){
            low[k] = dfn[k] = ++ tim;
            int cnt = 0, siz = 0;
            for(reg int i = head[k]; i; i = edge[i].nxt){
                    int to = edge[i].to;
                    if(dfn[to]) low[k] = std::min(low[k], dfn[to]);
                    else {
                            siz ++;
                            Tarjan(to);
                            low[k] = std::min(low[k], low[to]);
                            if(low[to] >= dfn[k]){
                                    cnt ++;
                                    if(k != root || cnt > 1) cut[k] = 1;
                            }
                    }
            }
    }
    
    • ()缩点(边双)

    将边双联通分量缩点 .

    DFSDFS 时, 定义同上, 每次将当前节点压入 中,
    low[k]=dfn[k]low[k]=dfn[k] 时, 说明kk节点以下在 中的元素共同构成一个 强联通分量,
    此时弹出 内元素, 得到新的环.
    与上方判环的方式不同的是, 这里开了个 in_stk[]in\_stk[] 数组, 来判断是否在环内.

    注意: 只有在栈中, 才能用来更新 lowlow

    void Tarjan(int k){
            Dfn[k] = low[k] = ++ t_num;
            stk.push(k);
            in_stk[k] = 1;
            for(int i = head[k]; i; i = edge[i].next){
                    int t = edge[i].to;
                    if(!Dfn[t]) Tarjan(t), low[k] = std::min(low[k], low[t]);       //WRONG #1
                    else if(in_stk[t]) low[k] = std::min(low[k], Dfn[t]);
            }
            if(Dfn[k] == low[k]){
                    block[k] = ++ block_num;
                    block_size[block_num] ++;
                    while(stk.top() != k){
                            block[stk.top()] = block_num;
                            block_size[block_num] ++;
                            in_stk[stk.top()] = 0;
                            stk.pop();
                    }
                    in_stk[k] = 0;
                    stk.pop();
            }
    }
    
    • ()缩点(点双)

    将点双联通分量缩点 .

    DFSDFS 时, 设当前节点为 kk, 连向的节点为 toto,

    • toto 访问过且 dfsdfs序比 kk 小, 说明 totokk 为一个环的首尾, 将边 k,tok, to 加入栈中 .
    • toto 没有访问过, 先将边 k,tok, to 加入栈中, 递归处理 toto, 然后检查 low[to]low[to] 是否大于等于 dfn[k]dfn[k],
      若小于, 则不用管, 会在 low[to]low[to] 处通过弹栈操作处理掉 首 为 low[to]low[to] 的环,
      若大于等于, 说明 toto 可能在 kk 以下构成了环, 也可能与 kk 在同一个环内,
      • 对第一种情况, kktoto 通过弹栈操作仍然能构成点双联通 .
      • 对第二种情况, kktotoDFSDFS kk 这层可以通过弹栈操作找出环 .
    void Tarjan(int k, int fa){
            low[k] = dfn[k] = ++ tim; 
            for(reg int i = head[k]; i; i = edge[i].nxt){
                    int to = edge[i].to;
                    if(!dfn[to]){
                            stk.push(k), stk_2.push(to);
                            Tarjan(to, k), low[k] = std::min(low[k], low[to]);
                            if(low[to] < dfn[k]) continue ;
                            bk_cnt ++;
                            while(!stk.empty()){
                                    int tp = stk.top(), tu = stk_2.top();
                                    bk[bk_cnt].pb(tp), bk[bk_cnt].pb(tu);
                                    stk.pop(), stk_2.pop();
                                    if(tp == k && tu == to) break ;
                            }
                    }else if(dfn[to] < dfn[k] && to != fa){
                            stk.push(k), stk_2.push(to);
                            low[k] = std::min(low[k], dfn[to]);
                    }
            }
    }
    

    • 相关例题

    1. 例题1
    2. 例题2
    3. 例题3
    4. 例题4
  • 相关阅读:
    codeforces round #234B(DIV2) B Inna and New Matrix of Candies
    关于禁止ipad的home键解决方法
    ios cocos2d 画线出现闪烁问题
    ios 关于[xxx timeIntervalSinceNow]出现EXC_BAD_ACCESS错误的解决办法
    Codeforces Round #228 (Div. 2) B. Fox and Cross
    Codeforces Round #228 (Div. 2) A. Fox and Number Game
    c语言 %p
    xcode 编译opencv ios容易出现的错误
    ios编译ASIHTTPRequest时出现 'libxml/HTMLparser.h' file not found in ASIHTTPRequest
    当编译CCBReader时出现 “ CCBAnimationManager.m Use of undeclared identifier 'other‘ ” 解决方法
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822550.html
Copyright © 2011-2022 走看看