【洛谷P2245】星際導航
阿新 • • 發佈:2018-10-31
題面
題解
\(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; }