1. 程式人生 > >洛谷P2245 星際導航(kruskal重構樹)

洛谷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;
}