原題傳送門
最小瓶頸路
與NOIp題貨車運輸類似
建最小生成樹,表維護最大值
Code:
#include <bits/stdc++.h>
#define maxn 300010
using namespace std;
struct Edge{
int to, next, len;
}edge[maxn << 1];
struct Line{
int x, y, z;
}line[maxn];
int num, head[maxn], f[maxn], d[maxn], len[maxn][25], fa[maxn][25], n, m, q;
inline int read(){
int s = 0, w = 1;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) + (c ^ 48);
return s * w;
}
bool cmp(Line x, Line y){ return x.z < y.z; }
void addedge(int x, int y, int z){ edge[++num] = (Edge){y, head[x], z}, head[x] = num; }
int getfa(int k){ return k == f[k] ? k : f[k] = getfa(f[k]); }
void dfs(int u, int pre){
d[u] = d[pre] + 1, fa[u][0] = pre;
for (int i = 0; fa[u][i]; ++i) fa[u][i + 1] = fa[fa[u][i]][i], len[u][i + 1] = max(len[u][i], len[fa[u][i]][i]);
for (int i = head[u]; i; i = edge[i].next){
int v = edge[i].to;
if (v != pre) len[v][0] = edge[i].len, dfs(v, u);
}
}
int lca(int u, int v){
int sum = 0;
if (d[u] >= d[v]) swap(u, v);
for (int i = 20; i >= 0; --i) if (d[u] <= d[v] - (1 << i)) sum = max(sum, len[v][i]), v = fa[v][i];
if (u == v) return sum;
for (int i = 20; i >= 0; --i)
if (fa[u][i] != fa[v][i]) sum = max(sum, max(len[u][i], len[v][i])), u = fa[u][i], v = fa[v][i];
return max(sum, max(len[u][0], len[v][0]));
}
int main(){
n = read(), m = read();
for (int i = 1; i <= m; ++i) line[i] = (Line){read(), read(), read()};
sort(line + 1, line + 1 + m, cmp);
for (int i = 1; i <= n; ++i) f[i] = i;
for (int i = 1; i <= m; ++i){
int s1 = getfa(line[i].x), s2 = getfa(line[i].y);
if (s1 != s2){
f[s1] = s2;
addedge(line[i].x, line[i].y, line[i].z), addedge(line[i].y, line[i].x, line[i].z);
}
}
for (int i = 1; i <= n; ++i)
if (!d[i]) dfs(i, 0);
q = read();
while (q--){
int x = read(), y = read(), s1 = getfa(x), s2 = getfa(y);
if (s1 != s2) puts("impossible"); else printf("%d\n", lca(x, y));
}
return 0;
}