firiexp's Library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub firiexp/library

:heavy_check_mark: 橋木(Bridge Tree)
(graph/bridge_tree.cpp)

説明

無向グラフの二辺連結成分を縮約して、橋だけを辺に持つ森を作る。 連結グラフなら木、非連結グラフなら森になる。

できること

使い方

build() 後は treenodesedgesid を参照する。

tecc に内部の TwoEdgeConnectedComponents を保持しているので、必要なら ordlow も参照できる。

Depends on

Verified with

Code

using namespace std;

#include "twoedgeconnectedcomponents.cpp"

struct BridgeTree {
    int n, component_count;
    TwoEdgeConnectedComponents tecc;
    vector<vector<int>> tree, nodes;
    vector<pair<int, int>> edges;
    vector<int> id;

    explicit BridgeTree(int n) : n(n), component_count(0), tecc(n), id(n, -1) {}

    void add_edge(int u, int v) {
        tecc.add_edge(u, v);
    }

    int build() {
        component_count = tecc.build();
        id = tecc.bridge;
        nodes = tecc.out;
        tree.assign(component_count, {});
        edges.clear();
        for (int i = 0; i < n; ++i) {
            for (auto &&j : tecc.G[i]) {
                if (i < j && tecc.is_bridge(i, j)) {
                    int u = id[i], v = id[j];
                    tree[u].push_back(v);
                    tree[v].push_back(u);
                    edges.emplace_back(u, v);
                }
            }
        }
        return component_count;
    }
};

/**
 * @brief 橋木(Bridge Tree)
 */
#line 1 "graph/bridge_tree.cpp"
using namespace std;

#line 1 "graph/twoedgeconnectedcomponents.cpp"
class TwoEdgeConnectedComponents {
    void dfs(int i, int &pos){
        ord[i] = low[i] = pos++;
        int mul = 0;
        for (auto &&j : G[i]) {
            if(j == par[i] && !mul){
                mul = 1;
                continue;
            }
            if(~ord[j]){
                low[i] = min(low[i], ord[j]);
                continue;
            }
            par[j] = i;
            dfs(j, pos);
            size[i] += size[j];
            low[i] = min(low[i], low[j]);
        }
    }

    void dfs2(int i){
        out[bridge[i]].emplace_back(i);
        for (auto &&j : G[i]) {
            if(~bridge[j] || is_bridge(i, j)) continue;
            bridge[j] = bridge[i];
            dfs2(j);
        }
    }
public:
    vector<int> ord, low, par, bridge, size;
    vector<vector<int>> G, out;
    explicit TwoEdgeConnectedComponents(int n): ord(n, -1), low(n), par(n, -1), bridge(n, -1), size(n, 1), G(n){}

    inline bool is_bridge(int i, int j){
        if(ord[i] > ord[j]) swap(i, j);
        return ord[i] < low[j];
    }

    void add_edge(int u, int v){
        if(u != v){
            G[u].emplace_back(v);
            G[v].emplace_back(u);
        }
    }

    int build(){
        int n = G.size(), pos = 0;
        for (int i = 0; i < n; ++i) {
            if(ord[i] < 0) dfs(i, pos);
        }
        int k = 0;
        for (int i = 0; i < n; ++i) {
            if(!~bridge[i]){
                bridge[i] = k++;
                out.emplace_back();
                dfs2(i);
            }
        }
        return k;
    }
};

/**
 * @brief 二辺連結成分分解(Two-Edge-Connected Components)
 */
#line 4 "graph/bridge_tree.cpp"

struct BridgeTree {
    int n, component_count;
    TwoEdgeConnectedComponents tecc;
    vector<vector<int>> tree, nodes;
    vector<pair<int, int>> edges;
    vector<int> id;

    explicit BridgeTree(int n) : n(n), component_count(0), tecc(n), id(n, -1) {}

    void add_edge(int u, int v) {
        tecc.add_edge(u, v);
    }

    int build() {
        component_count = tecc.build();
        id = tecc.bridge;
        nodes = tecc.out;
        tree.assign(component_count, {});
        edges.clear();
        for (int i = 0; i < n; ++i) {
            for (auto &&j : tecc.G[i]) {
                if (i < j && tecc.is_bridge(i, j)) {
                    int u = id[i], v = id[j];
                    tree[u].push_back(v);
                    tree[v].push_back(u);
                    edges.emplace_back(u, v);
                }
            }
        }
        return component_count;
    }
};

/**
 * @brief 橋木(Bridge Tree)
 */
Back to top page