【模板】Kruskal重构树

Kruskal 重构树模板

知识点

  • Kruskal 算法
  • LCA(倍增LCA或者Trajan算法)

模板

这里使用用倍增LCA。例题为:P1967 火车运输。

除了Kruskal求生成树含在main函数里面,其他都已经用结构体封装好。

#include 
using namespace std;
#define all(x) std::begin(x), std::end(x)

const int MAXN = 1e6 + 10;
int n, m;

vector<int>g[MAXN];
inline void pushedge(int u, int v) {
    g[u].push_back(v);
}

int tot = 0;
int W[MAXN] = {};

// 并查集
struct Dset {
    vector<int>dad;
    void inti(int size) {
        dad.assign(size + 1, -1);
    }
    int &operator [] (int i) {
        return dad[i];
    }
    int Find(int v) {
        if (dad[v] != - 1) {
            return dad[v] = Find(dad[v]);
        }
        return v;
    }
    bool Union(int a, int b) {
        a = Find(a);
        b = Find(b);
        if (a == b) 
            return false;
        dad[a] = b;
        return true;
    }
};

// LCA
struct LCA {
    vector<vector<int>>fa;  
    vector<int>lg, depth;
    void inti(int size) {
        fa.assign(size + 1, vector<int>(32, 0));
        lg.assign(size + 1, 0);
        depth.assign(size + 1, 0);
        lg[2] = 1;
        for (int i = 3; i < lg.size(); ++ i) {
            lg[i] = lg[i >> 1] + 1;
        }
    }
    void dfs(int now, int dad) {
        fa[now][0] = dad;
        depth[now] = depth[dad] + 1;
        for (int i = 1; i <= lg[depth[now]]; ++ i) {
            fa[now][i] = fa[fa[now][i - 1]][i - 1];
        }
        for (auto nex : g[now]) {
            if (dad != nex) {
                dfs(nex, now);
            }
        }
    }
    int lca(int a, int b) {
        if (depth[a] < depth[b]) {
            swap(a, b);
        }
        while (depth[a] > depth[b]) {
            a = fa[a][lg[depth[a] - depth[b]]];
        }
        if (a == b) {
            return a;
        }
        for (int i = lg[depth[a]]; i >= 0; -- i) {
            if (fa[a][i] != fa[b][i]) {
                a = fa[a][i];
                b = fa[b][i];
            }
        }
        return fa[a][0];
    }
};

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    cin >> n >> m;

    struct Node {
        int u, v, w;
        bool operator < (const Node &a) const {
            return w > a.w;
        }
    };
    vector<Node>ed(m);
    for (auto &[u, v, w] : ed) {
        cin >> u >> v >> w;
    }
    sort(all(ed));

    Dset dset;
    dset.inti(n + m + 1);
    tot = n;
    for (const auto [u, v, w] : ed) {
        int du = dset.Find(u), dv = dset.Find(v);
        if (du != dv) {
            tot ++;
            dset[du] = dset[dv] = tot;
            W[tot] = w;
            pushedge(tot, du);
            pushedge(tot, dv);
            pushedge(du, tot);
            pushedge(dv, tot);
        }
    }

    LCA lca;
    lca.inti(tot + 1);
    for (int i = 1; i <= tot; ++ i) {
        if (dset.Find(i) == i) {
            lca.dfs(i, 0);
        }
    }
    
    int t;
    cin >> t;
    while (t --) {
        int a, b;
        cin >> a >> b;
        if (dset.Find(a) != dset.Find(b)) {
            cout << -1 << '\n';
        } else {
            cout << W[lca.lca(a, b)] << '\n';
        }
    }


    return 0;
}

你可能感兴趣的:(模板,图论,图论,算法)