洛谷P1967 货车运输
\(\large{题目链接}\)
\(\\\)
\(\Large\textbf{Solution: } \large{注意到两地之间的路径可能有多条,又要使路径上的边权最小最大,想到最大生成树。\\先建树,然后树上倍增即可。\\值得注意的是,图中所有点不一定联通,所以搜索时要谨慎。}\)
\(\Large\textbf{Code: }\)
#include <bits/stdc++.h>
#define gc() getchar()
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
using namespace std;
const int N = 1e4 + 5;
const int M = 5e4 + 5;
const int inf = 0x7fffffff;
int n, m, cnt, f[N], h[N], head[N], vis[N], lg[N], dep[N], Min[N][20], fa[N][20];
struct Edge {
int fro, to, val;
}E[M];
struct EDGE {
int to, next, val;
}e[N << 1];
inline int read() {
int x = 0;
char ch = gc();
while (!isdigit(ch)) ch = gc();
while (isdigit(ch)) x = x * 10 + ch - '0', ch = gc();
return x;
}
inline void add(int x, int y, int w) {
e[++cnt].to = y;
e[cnt].next = head[x];
e[cnt].val = w;
head[x] = cnt;
}
inline int find(int x) {
if (x == f[x]) return x;
return f[x] = find(f[x]);
}
inline bool cmp(Edge a, Edge b) {
return a.val > b.val;
}
inline void Kruskal() {
rep(i, 1, n) f[i] = i;
sort(E + 1, E + m + 1, cmp);
int tot = 0;
for (int i = 1; i <= m; ++i) {
int u = find(E[i].fro), v = find(E[i].to);
if (u != v) f[v] = u, ++tot, add(E[i].fro, E[i].to, E[i].val), add(E[i].to, E[i].fro, E[i].val);
if (tot == n - 1) break;
}
return;
}
inline void dfs(int x, int fat, int w) {
vis[x] = 1;
fa[x][0] = fat;
Min[x][0] = w;
dep[x] = dep[fat] + 1;
for (int i = 1; (1 << i) <= dep[x]; ++i) {
fa[x][i] = fa[fa[x][i - 1]][i - 1];
Min[x][i] = min(Min[x][i - 1], Min[fa[x][i - 1]][i - 1]);
}
for (int i = head[x]; i ; i = e[i].next) if (e[i].to != fat) dfs(e[i].to, x, e[i].val);
}
inline int sol(int x, int y) {
if (find(x) != find(y)) return -1;
int ans = inf;
if (dep[x] < dep[y]) swap(x, y);
while (dep[x] > dep[y]) ans = min(ans, Min[x][lg[dep[x] - dep[y]]]), x = fa[x][lg[dep[x] - dep[y]]];
if (x == y) return ans;
for (int i = lg[dep[x]]; i >= 0; --i) if (fa[x][i] != fa[y][i]) ans = min(ans, min(Min[x][i], Min[y][i])), x = fa[x][i], y = fa[y][i];
ans = min(ans, min(Min[x][0], Min[y][0]));
return ans;
}
int main() {
n = read(), m = read();
int x, y, w;
rep(i, 2, n) lg[i] = lg[i >> 1] + 1;
for (int i = 1; i <= m; ++i) E[i].fro = read(), E[i].to = read(), E[i].val = read();
Kruskal();
rep(i, 1, 20) rep(j, 1, n) Min[i][j] = inf;
rep(i, 1, n)
if (!dep[i]) {
dep[i] = 0;
dfs(i, 0, inf);
}
m = read();
while (m--) {
x = read(), y = read();
if (!vis[x] || !vis[y]) { puts("-1"); continue; }
printf("%d\n", sol(x, y));
}
return 0;
}