图论-割点与点双连通分量

首先是两篇的代码

割点

点击查看代码
int head[N], cnt = 0;
struct Edge{
    int from, to, nxt;
}e[N << 1];
void add(int u, int v){
    e[++cnt].from = u;
    e[cnt].to = v;
    e[cnt].nxt = head[u];
    head[u] = cnt;
}

int dfn[N], back[N], tim; // dfn[i] 时间戳  back[i] 回退到祖先
bool iscut[N]; // 结果数组

void dfs(int u, int fa){
    dfn[u] = back[u] = ++tim;
    int child = 0;
    for(int i = head[u]; i != 0; i = e[i].nxt){
        int v = e[i].to;
        if(!dfn[v]){
            dfs(v, u);
            back[u] = min(back[u], back[v]);
            if(back[v] >= dfn[u]){
                child++; // 事实上,child 只对于 root 生效,而当 u 是 root 时,上面的 if 语句是恒成立的
                if(u != root || child > 1)
                    iscut[u] = true;
            }
        }
        else if(v != fa){
            back[u] = min(back[u], dfn[v]); // 注意不是  back[v]
        }
    }
}

点双连通分量

点击查看代码
int head[N], cnt = 0;
struct Edge{
    int from, to, nxt;
}e[N << 1];
void add(int u, int v){
    e[++cnt].from = u;
    e[cnt].to = v;
    e[cnt].nxt = head[u];
    head[u] = cnt;
}

int dfn[N], back[N], tim, root, dcc_cnt, inde[N]; // dfn[i] 时间戳  back[i] 回退到祖先
bool iscut[N]; // 结果数组
stack<int> stk;
vector<int> dcc[N];


void dfs(int u, int fa){
    dfn[u] = back[u] = ++tim;
    stk.push(u);
    // 孤立点判断
    if(inde[u] == 0){
        dcc[++dcc_cnt].push_back(u);
        return ;
    }
    int child = 0;
    for(int i = head[u]; i != 0; i = e[i].nxt){
        int v = e[i].to;
        if(!dfn[v]){
            dfs(v, u);
            back[u] = min(back[u], back[v]);
            if(back[v] >= dfn[u]){
                child++; // 事实上,child 只对于 root 生效,而当 u 是 root 时,上面的 if 语句是恒成立的
                if(u != root || child > 1)
                    iscut[u] = true;
                dcc_cnt++; // 不在割点判断范围内的原因在于 根节点的特殊情况,即该点不是割点,但因为是最后一个区域,所以也要自成一组
                while(1){
                    int z = stk.top(); stk.pop();
                    dcc[dcc_cnt].push_back(z);
                    if(z == v) break;
                }
                dcc[dcc_cnt].push_back(u);
            }
        }
        else if(v != fa){
            back[u] = min(back[u], dfn[v]); // 注意不是  back[v]
        }
    }
}

  • 更新的原因:点双连通分量是根据割点来求的,割点会分到它每一个子图中
posted @ 2024-05-22 18:47  9102700  阅读(17)  评论(0)    收藏  举报