library

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


Project maintained by tko919 Hosted on GitHub Pages — Theme by mattgraham

:heavy_check_mark: Auxiliary Tree(Virtual Tree)
(Graph/auxiliarytree.hpp)

Depends on

Verified with

Code

#pragma once

#include "Graph/lca.hpp"

struct AuxiliaryTree{
    int n,pos;
    LCA lca;
    vector<int> in,dep;
    vector<vector<int>> _g,g;
    AuxiliaryTree(int _n):n(_n),pos(0),lca(n),in(n),dep(n),_g(n),g(n){}
    void add_edge(int u,int v){
        lca.add_edge(u,v);
        _g[u].push_back(v);
        _g[v].push_back(u);
    }
    void run(int root=0){
        lca.run(root);
        dfs(root,-1);
    }
    void query(vector<int>& vs){
        sort(ALL(vs),[&](int u,int v){return in[u]<in[v];});
        vs.erase(unique(ALL(vs)),vs.end());
        int m=vs.size();
        stack<int> st;
        st.push(vs[0]);
        rep(i,0,m-1){
            int w=lca.lca(vs[i],vs[i+1]);
            if(w!=vs[i]){
                int cur=st.top();
                st.pop();
                while(!st.empty() and dep[w]<dep[st.top()]){
                    add(st.top(),cur);
                    cur=st.top();
                    st.pop();
                }
                if(st.empty() or st.top()!=w){
                    st.push(w);
                    vs.push_back(w);
                }
                add(w,cur);
            }
            st.push(vs[i+1]);
        }
        while(st.size()>1){
            int c=st.top();
            st.pop();
            add(st.top(),c);
        }
    }
    void clear(vector<int>& vs){
        for(auto& w:vs)g[w].clear();
    }
private:
    void dfs(int v,int p){
        in[v]=pos++;
        for(auto& to:_g[v])if(to!=p){
            dep[to]=dep[v]+1;
            dfs(to,v);
        }
    }
    void add(int u,int v){
        g[u].push_back(v);
        g[v].push_back(u);
    }
};

/**
 * @brief Auxiliary Tree(Virtual Tree)
 */
#line 2 "Graph/auxiliarytree.hpp"

#line 2 "Graph/lca.hpp"

struct LCA {
    LCA(int _n = 0) : n(_n), g(_n), depth(_n + 1, inf), start(_n) {}
    void add_edge(int u, int v) {
        g[u].push_back(v);
        g[v].push_back(u);
    }
    void run(int root = 0) {
        depth[root] = 0;
        dfs(root, -1);
        N = 1;
        while (N < int(euler.size()))
            N <<= 1;
        tree.resize(N * 2, n);
        rep(i, 0, euler.size()) tree[N + i] = euler[i];
        for (int i = N - 1; i > 0; i--)
            tree[i] = op(tree[i * 2], tree[i * 2 + 1]);
    }
    int lca(int u, int v) {
        int a = start[u], b = start[v];
        if (a > b)
            swap(a, b);
        b++;
        int res = n;
        for (int T = b - a; T >= 1; T = b - a) {
            int x = a | ((1U << 31) >> __builtin_clz(T));
            int y = x & -x, k = __builtin_ctz(x);
            res = op(res, tree[(N | a) >> k]);
            a += y;
        }
        return res;
    }
    int dist(int u, int v) {
        return depth[u] + depth[v] - depth[lca(u, v)] * 2;
    }

  private:
    int n, N;
    vector<vector<int>> g;
    vector<int> depth, start, euler, tree;
    void dfs(int v, int p) {
        start[v] = euler.size();
        euler.push_back(v);
        for (auto &to : g[v])
            if (to != p) {
                depth[to] = depth[v] + 1;
                dfs(to, v);
                euler.push_back(v);
            }
    }
    int op(int u, int v) {
        if (depth[u] < depth[v])
            return u;
        else
            return v;
    }
};

/**
 * @brief Lowest Common Ancestor
 */
#line 4 "Graph/auxiliarytree.hpp"
struct AuxiliaryTree{
    int n,pos;
    LCA lca;
    vector<int> in,dep;
    vector<vector<int>> _g,g;
    AuxiliaryTree(int _n):n(_n),pos(0),lca(n),in(n),dep(n),_g(n),g(n){}
    void add_edge(int u,int v){
        lca.add_edge(u,v);
        _g[u].push_back(v);
        _g[v].push_back(u);
    }
    void run(int root=0){
        lca.run(root);
        dfs(root,-1);
    }
    void query(vector<int>& vs){
        sort(ALL(vs),[&](int u,int v){return in[u]<in[v];});
        vs.erase(unique(ALL(vs)),vs.end());
        int m=vs.size();
        stack<int> st;
        st.push(vs[0]);
        rep(i,0,m-1){
            int w=lca.lca(vs[i],vs[i+1]);
            if(w!=vs[i]){
                int cur=st.top();
                st.pop();
                while(!st.empty() and dep[w]<dep[st.top()]){
                    add(st.top(),cur);
                    cur=st.top();
                    st.pop();
                }
                if(st.empty() or st.top()!=w){
                    st.push(w);
                    vs.push_back(w);
                }
                add(w,cur);
            }
            st.push(vs[i+1]);
        }
        while(st.size()>1){
            int c=st.top();
            st.pop();
            add(st.top(),c);
        }
    }
    void clear(vector<int>& vs){
        for(auto& w:vs)g[w].clear();
    }
private:
    void dfs(int v,int p){
        in[v]=pos++;
        for(auto& to:_g[v])if(to!=p){
            dep[to]=dep[v]+1;
            dfs(to,v);
        }
    }
    void add(int u,int v){
        g[u].push_back(v);
        g[v].push_back(u);
    }
};

/**
 * @brief Auxiliary Tree(Virtual Tree)
 */
Back to top page