[NOIP2013]货车运输 倍增 生成树

学克鲁斯卡尔重构树打的板子ovo 要学克鲁斯卡尔重构树见上一篇转的博客很详细
~~直接贴代码啦

#include<bits/stdc++.h>
#define For(i, a, b) for(register int i = a; i <= b; ++ i)
#define go(x, i) for(register int i = head[x]; i; i = nxt[i])
#define FOR(i, a, b) for(register int i = a; i >= b; -- i)

using namespace std;

const int maxn = 2e5 + 10;
int to[maxn << 1], head[maxn], nxt[maxn << 1], e;
int n, m, q, val[maxn], fa[maxn];
int f[maxn][20], dep[maxn];

struct egde
{
    int x, y, z;
}E[maxn];

bool cmp(egde A, egde B)
{
    return A.z > B.z;
}

void add(int x, int y)
{
    to[++ e] = y;
    nxt[e] = head[x];
    head[x] = e;
}

int find(int x)
{
    return fa[x] = x == fa[x] ? x : find(fa[x]);
}

void dfs(int x)
{
    go(x, i)
        if(!dep[to[i]])
        {
            dep[to[i]] = dep[x] + 1;
            f[to[i]][0] = x;
            dfs(to[i]);
        }
}

int lca(int x, int y)
{
    if(dep[x] != dep[y])
    {
        if(dep[y] > dep[x])
            swap(x, y);
        FOR(j, 19, 0)
            if(dep[f[x][j]] > dep[y])
                x = f[x][j];
        x = f[x][0];
    }
    if(x == y)
        return x;
    FOR(j, 19, 0)
        if(f[x][j] != f[y][j])
            x = f[x][j], y = f[y][j];
    if(x != y)
        x = f[x][0];
    return x;
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("1967.in", "r", stdin);
    freopen("1967.out", "w", stdout);
#endif
    int x, y;
    scanf("%d%d", &n, &m);
    For(i, 1, m)
        scanf("%d%d%d", &E[i].x, &E[i].y, &E[i].z);
    For(i, 1, n + m)
        fa[i] = i;
    sort(E + 1, E + m + 1, cmp);
    For(i, 1, m)
    {
        int u = find(E[i].x), v = find(E[i].y);
        if(u != v)
        {
            fa[u] = fa[v] = fa[i + n];
            add(i + n, u), add(u, i + n);
            add(i + n, v), add(v, i + n);
        }
    }
    For(i, 1, m)
        if(fa[n + i] == n + i)
            dep[n + i] = 1, dfs(n + i);
    For(j, 1, 19)
        For(i, 1, n + m)
            f[i][j] = f[f[i][j - 1]][j - 1];
    scanf("%d", &q);
    while(q --)
    {
        scanf("%d%d", &x, &y);
        if(find(x) != find(y))
            puts("-1");
        else
            printf("%d\n", E[lca(x, y) - n].z);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/lunch__/article/details/81116645