询问一些tarjan割点写法的正确性(求hack)
  • 板块学术版
  • 楼主hyj0824
  • 当前回复0
  • 已保存回复0
  • 发布时间2023/3/25 16:41
  • 上次更新2023/10/23 20:32:47
查看原帖
询问一些tarjan割点写法的正确性(求hack)
117307
hyj0824楼主2023/3/25 16:41

rt,下面是两个我见到过的写法:

第一个只记录根节点的子节点数

第二个会记录每个节点的子节点数

void tarjan(int now, const int& root) {
    low[now] = dfn[now] = ++id;
    int child = 0; // 累计该节点有几个儿子
    for (int ch : edge[now]) {
        if (!dfn[ch]) {
            // 没有访问过 直接tarjan它
            tarjan(ch, root);
            low[now] = std::min(low[now], low[ch]);

            if (now == root)
                child++;
            // 相较于缩点,割点在这里就可以判断
            if (low[ch] >= dfn[now]) {
                // 对于根节点,儿子大于1;对于其他点,直接更新
                if (root != now || child > 1) {
                    is_cut[now] = 1;
                }
            }
        } else
            low[now] = std::min(low[now], dfn[ch]);
        // low存储**不经过**父亲节点可以抵达的最早节点
        // 如果右边ch的dfn写成low 而low可能会被更新得比dfn更小
        // 那么这样处理得到的low 事实上是经过了父亲节点的
    }
}
void tarjan(int now, const int& root) {
    low[now] = dfn[now] = ++id;
    int child = 0; // 累计该节点有几个儿子
    for (int ch : edge[now]) {
        if (!dfn[ch]) {
            // 没有访问过 直接tarjan它
            tarjan(ch, root);
            low[now] = std::min(low[now], low[ch]);

            // 相较于缩点,割点在这里就可以判断
            if (low[ch] >= dfn[now]) {
                child++;
                // 对于根节点,儿子大于1;对于其他点,直接更新
                if (root != now || child > 1) {
                    is_cut[now] = 1;
                }
            }
        } else
            low[now] = std::min(low[now], dfn[ch]);
        // low存储**不经过**父亲节点可以抵达的最早节点
        // 如果右边ch的dfn写成low 而low可能会被更新得比dfn更小
        // 那么这样处理得到的low 事实上是经过了父亲节点的
    }
}
2023/3/25 16:41
加载中...