【洛谷P2245】星际导航

题面

题解

\(kruskal\)重构树板子题??(大雾

因为重构树上两点之间的\(LCA\)的权值就是原图上最小生成树上的瓶颈。

所以建个重构树,跑\(LCA\)即可。

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#define RG register
#define file(x) freopen(#x".in", "r", stdin);freopen(#x".out", "w", stdout);

inline int read()
{
    int data = 0, w = 1;
    char ch = getchar();
    while(ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
    if(ch == '-') w = -1, ch = getchar();
    while(ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
    return data * w;
}

const int maxn(2e5 + 10), maxm(3e5 + 10);
struct edge { int next, to; } e[maxn << 2];
struct Edge { int from, to, dis; } E[maxm];

inline bool cmp(const Edge &lhs, const Edge &rhs) { return lhs.dis < rhs.dis; }
int fa[maxn], f[maxn], size[maxn], belong[maxn], heavy[maxn], head[maxn], e_num, cnt, pos[maxn], val[maxn], n, m, n_cnt;
inline void add_edge(int from, int to) { e[++e_num] = (edge) {head[from], to}; head[from] = e_num; }

void dfs(int x)
{
    size[x] = 1;
    for(RG int i = head[x]; i; i = e[i].next)
    {
        int to = e[i].to; if(to == fa[x]) continue;
        fa[to] = x; dfs(to); size[x] += size[to];
        if(size[heavy[x]] < size[to]) heavy[x] = to;
    }
}

void dfs(int x, int chain)
{
    pos[x] = ++cnt; belong[x] = chain;
    if(!heavy[x]) return;
    dfs(heavy[x], chain);
    for(RG int i = head[x]; i; i = e[i].next)
    {
        int to = e[i].to; if(to == fa[x] || to == heavy[x]) continue;
        dfs(to, to);
    }
}

inline int LCA(int a, int b)
{
    while(belong[a] != belong[b])
    {
        if(pos[belong[a]] < pos[belong[b]]) std::swap(a, b);
        a = fa[belong[a]];
    }
    return pos[a] < pos[b] ? a : b;
}

inline int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); }
inline void Kruskal()
{
    std::sort(E + 1, E + m + 1, cmp); n_cnt = n;
    for(RG int i = 1; i <= m; i++)
    {
        int fx = find(E[i].from), fy = find(E[i].to);
        if(fx == fy) continue;
        f[fx] = f[fy] = ++n_cnt; f[n_cnt] = n_cnt;
        add_edge(n_cnt, fx); add_edge(fx, n_cnt);
        add_edge(n_cnt, fy); add_edge(fy, n_cnt);
        val[n_cnt] = E[i].dis;
    }

    for(RG int i = n_cnt; i; i--)
        if(!pos[i]) dfs(i), dfs(i, i);
}

int main()
{
#ifndef ONLINE_JUDGE
    file(cpp);
#endif
    n = read(); m = read();
    for(RG int i = 1; i <= m; i++) E[i] = (Edge) {read(), read(), read()};
    for(RG int i = 1; i <= n; i++) f[i] = i;
    RG int q = read(); Kruskal();
    while(q--)
    {
        int a = read(), b = read();
        if(find(a) != find(b)) puts("impossible");
        else printf("%d\n", val[LCA(a, b)]);
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/cj-xxz/p/9884496.html