Kruskal重构树 +倍增LCA 10pts求调,玄关
查看原帖
Kruskal重构树 +倍增LCA 10pts求调,玄关
759274
Stevehim楼主2023/11/23 09:11
#include <bits/stdc++.h>
#define maxn 1001000
#define int long long
#define re register
using namespace std;
struct EDGE{
    int from, to, w;
    bool operator < (const EDGE &b) const{
        return w > b.w;
    }
}e[maxn];
struct node{
    int nxt, to;
}a[maxn];
int head[maxn], cnt, tot; //cnt:加边用,tot:加点用
int n, m, q, u, v, fa[maxn], d[maxn];
inline void add(int a1, int b){
    a[++cnt].nxt = head[a1];
    a[cnt].to = b;
    head[a1] = cnt;
}
inline int find(int x){
    if(fa[x] == x) return x; 
    return fa[x] = find(fa[x]);
}

int f[maxn][32], dep[maxn], lg[maxn];
bool book[maxn];

inline void dfs(int u,int father){ //预处理LCA
    book[u] = true, dep[u] = dep[father] + 1,f[u][0] = father;
    for(re int i = 1; i <= dep[u]; i++) f[u][i] = f[f[u][i - 1]][i - 1];
    for(re int i = head[u]; i; i = a[i].nxt) if(a[i].to != father) dfs(a[i].to, u);
}

inline void Kruskal(){ //最大生成树
    sort(e + 1,e + 1 + m);
    for(int i = 1; i <= n * 2; i++) fa[i] = i;
    int cnt = 0;
    for(re int i = 1; i <= m; i++){
        if(cnt == n - 1) break;
        int u = find(e[i].from), v = find(e[i].to);
        if(u != v){
            cnt++;
            d[++tot] = e[i].w;
            fa[u] = fa[v] = tot;
            add(tot, u), add(tot, v);
        }
    }
    for(re int i = tot;i > n; i--) if(!book[i]) dfs(i, i);
}

inline int LCA(int x,int y){
    if(x == y) return x;
    if(dep[x] < dep[y]) swap(x, y);
    while(dep[x] > dep[y]) x = f[x][lg[dep[x] - dep[y]] - 1]; //调整
    if(x == y) return x;
    for(re int k = lg[dep[x]] - 1; k >= 0; k--) if(f[x][k] != f[y][k]) x = f[x][k], y = f[y][k];
    return f[x][0]; //同一高度,返回最近祖先
}

signed main(){
    // freopen("1.in", "r",stdin);
    // freopen("ans.out", "w", stdout);
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    cin >> n >> m;
    tot = n;
    for(re int i = 1; i <= n * 2 + 1; i++) lg[i] = lg[i >> 1] + 1;
    for(re int i = 1; i <= m; i++) cin >> e[i].from >> e[i].to >> e[i].w;
    cin >> q;
    Kruskal();
    while(q--){
        cin >> u >> v;
        if(find(u) != find(v)) cout << -1 << '\n';
        else cout << d[LCA(u, v)] << '\n';  
    }
    return 0;
}
2023/11/23 09:11
加载中...