洛谷P2245 星际导航(kruskal重构树)

传送门

感觉这题题目描述有点问题……

但是结合样例还是猜到了它的意思就是原图的最小生成树上两点间边权的最小值……

要不是样例我就写错了……

然后这题和NOIP2013货车运输并没有什么差别

kruskal重构树模板

注意可能不连通

#define MIAOKEHAO                                                                    \
            ┏┓  ┏┓                                                       \
           ┏┛┗━━┛┗━┓                                                   \
           ┃       ┃                                                   \
           ┃   ━    ┃                                                   \
           ┃ >   < ┃                                                   \
           ┃       ┃                                                   \
           ┃...  ⌒ ...  ┃                                                   \
           ┃       ┃                                                   \
           ┗━┓   ┏━┛                                                   \
             ┃   ┃ Code is far away from bug with the animal protecting \
             ┃   ┃  神兽保佑 , 代码无bug                                 \
             ┃   ┃                                            \
             ┃   ┃                                            \
             ┃   ┃                                            \
             ┃   ┃                                            \
             ┃   ┗━━━┓                                    \
             ┃       ┣┓                                  \
             ┃       ┏┛                                  \
             ┗┓┓┏━┳┓┏┛                                    \
              ┃┫┫ ┃┫┫                                      \
              ┗┻┛ ┗┻┛
#undef MIAOKEHAO
#include <bits/stdc++.h>
#define LL long long
#define db double
using namespace std;
typedef pair<LL, int> pli;
#define X first
#define Y second
#define mp make_pair

template < typename T > inline void read(T & x) {
    int ch = getchar();
    bool fg = false;
    for(x = 0; !isdigit(ch); ch = getchar()) {
        if(ch == '-') {
            fg = true;
        }
    }
    for(; isdigit(ch); ch = getchar()) {
        x = x * 10 + ch - '0';
    }
    if(fg) {
        x = -x;
    }
}

const int MAXN = 200200;
const int MAXE = 300300;
const int INF = (1u << 31) - 1;

struct edge {
    int u, v, len;
    edge() {
        u = v = len = 0;
    }
}e[MAXE];

bool operator < (edge a, edge b) {
    return a.len < b.len;
}

int n, m, Q;
int Fa[MAXN], rnk[MAXN];

int Find(int x) {
    return x == Fa[x] ? x : (Fa[x] = Find(Fa[x]));
}

int tot;
bool vis[MAXN];

void unite(int x, int y) {
    Fa[x] = Fa[y] = tot;
}

int h[MAXN], cnt, dep[MAXN], son[MAXN], fa[MAXN], sz[MAXN], top[MAXN], val[MAXN];

struct Edge {
    int to, nxt;
    Edge() {}
    Edge(int _to, int _nxt) : to(_to), nxt(_nxt) {}
}E[MAXE + MAXN];

inline void add_edge(int u, int v) {
    E[++cnt] = Edge(v, h[u]), h[u] = cnt;
    E[++cnt] = Edge(u, h[v]), h[v] = cnt;
}

void dfs1(int x) {
    dep[x] = dep[fa[x]] + 1, sz[x] = 1;
    vis[x] = 1;
    for(int i = h[x]; i; i = E[i].nxt) {
        int v = E[i].to;
        if(v == fa[x]) continue;
        fa[v] = x;
        dfs1(v);
        sz[x] += sz[v];
        if(sz[v] > sz[son[x]]) son[x] = v;
    }
}

void dfs2(int x) {
    if(x == son[fa[x]]) top[x] = top[fa[x]];
    else top[x] = x;
    if(son[x]) dfs2(son[x]);
    for(int i = h[x]; i; i = E[i].nxt) {
        int v = E[i].to;
        if(v == fa[x] || v == son[x]) continue;
        dfs2(v);
    }
}

int lca(int x, int y) {
    int f1 = top[x], f2 = top[y];
    while(f1 != f2) {
        if(dep[f1] < dep[f2]) swap(f1, f2), swap(x, y);
        x = fa[f1];
        f1 = top[x];
    }
    if(dep[x] > dep[y]) return y;
    else return x;
}

signed main() {
    read(n), read(m);
    for(int i = 1; i <= m; i++) {
        read(e[i].u), read(e[i].v), read(e[i].len);
    }
    sort(e + 1, e + m + 1);
    tot = n;
    for(int i = 1; i <= n * 2; i++) Fa[i] = i; 
    for(int i = 1; i <= m; i++) {
        int u = Find(e[i].u), v = Find(e[i].v), len = e[i].len;
        if(u != v) {
            val[++tot] = len;
            unite(u, v);
            add_edge(u, tot);
            add_edge(v, tot);
        }
    }
    for(int i = 1; i <= tot; i++) {
        if(!vis[i]) {
            int x = Find(i);
            dfs1(x);
            dfs2(x);
        }
    }
    read(Q);
    while(Q--) {
        int x, y;
        read(x), read(y);
        if(Find(x) == Find(y)) printf("%d\n", val[lca(x, y)]);
        else puts("impossible");
    }
    return 0;
}
发布了58 篇原创文章 · 获赞 34 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_37666409/article/details/83895659