Kruskal重构树求助
查看原帖
Kruskal重构树求助
483928
Z1qqurat楼主2023/8/9 16:16

Sub#0 前半部分WA后半部分TLE,思路是建出最大生成树的重构树,然后询问两点答案就是这两点的LCA。

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e4 + 5, M = 5e4 + 5;
int n, m, q, tot, fa[N][30], dep[N], d;
bool vis[N];
vector <int> T[N];

struct Ed{
    int u, v, w;
}ed[M];
bool cmp(Ed x, Ed y) {
    return x.w > y.w;
}

struct DSU{
    int fa[N], a[N]; //a存的是新加的节点的点权
    void init() {
        for (int i = 1; i <= n * 2; ++i) fa[i] = i;
        return ;
    }
    int getroot(int x) {
        if(fa[x] == x) return x;
        return fa[x] = getroot(fa[x]);
    }
    void merge(int x, int y, int w) {
        // x = getroot(x), y = getroot(y);
        fa[x] = fa[y] = ++n, a[n] = w;
        T[n].push_back(x), T[n].push_back(y);
        return ;
    }
}D;

void Kruskal() {
    D.init();
    sort(ed + 1, ed + m + 1, cmp);
    int cnt = 0;
    for (int i = 1; i <= m; ++i) {
        if(cnt == n - 1) break;
        int u = D.getroot(ed[i].u), v = D.getroot(ed[i].v);
        if(u == v) continue;
        cnt++;
        D.merge(u, v, ed[i].w);
        T[ed[i].u].push_back(ed[i].v), T[ed[i].v].push_back(ed[i].u);
    }
    d = log2(n);
    return ;
}

void dfs(int u, int ff) {
    vis[u] = 1, fa[u][0] = ff, dep[u] = dep[ff] + 1;
    for (int i = 0; i < T[u].size(); ++i) {
        int v = T[u][i];
        if(v == ff) continue;
        dfs(v, u);
    }
    return ;
}

int LCA(int x, int y) {
    if(x == y) return x;
    if(dep[x] < dep[y]) swap(x, y);
    for (int i = d; i >= 0; --i) {
        if(dep[fa[x][i]] > dep[y]) x = fa[x][i];
    }
    if(x == y) return x;
    for (int i = d; i >= 0; --i) {
        if(fa[x][i] != fa[y][i]) x = fa[x][i], y = fa[y][i];
    }
    // if(x == y) return x;
    return fa[x][0];
}

int main() {
    scanf("%d %d", &n, &m);
    tot = n;
    for (int i = 1; i <= m; ++i) {
        scanf("%d %d %d", &ed[i].u, &ed[i].v, &ed[i].w);
    }
    Kruskal();
    for (int i = n; i > tot; --i) {
        if(!vis[i]) dfs(i, i);
    }
    for (int i = 1; i <= d; ++i) {
        for (int j = 1; j <= n; ++j) {
            fa[j][i] = fa[fa[j][i - 1]][i - 1];
        }
    }
    scanf("%d", &q);
    for (int i = 1; i <= q; ++i) {
        int x, y; scanf("%d %d", &x, &y);
        if(D.getroot(x) != D.getroot(y)) puts("-1");
        else printf("%d\n", D.a[LCA(x, y)]);
    }
    return 0;
}
2023/8/9 16:16
加载中...