题目链接:传送门
kruskal重构树的板子题
和货车运输一样滴
会的可以写这个
我直接改的货车运输当时的倍增lca的代码
思路就是建出最小生成树
因为显然一些边权很大的边是不可能走的
然后倍增维护路径上边权的极值
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <complex>
#include <algorithm>
#include <climits>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define
#define
using namespace std;
typedef long long ll;
struct node {
int next, to, dis;
}edge[A];
struct TO {
int x, y, z;
friend bool operator < (const TO a, const TO b) {
return a.z < b.z;
}
}e[A];
int n, m, fa[A], vis[A], f[A][21], w[A][21], dep[A], a, b, c, q, faa[A];
int head[A], num_edge;
void add_edge(int from, int to, int dis) {
edge[++num_edge].next = head[from];
edge[num_edge].to = to;
edge[num_edge].dis = dis;
head[from] = num_edge;
}
int find(int x) {
if (fa[x] == x) return x;
else return fa[x] = find(fa[x]);
}
void kruskal() {
for (int i = 1; i <= n; i++) fa[i] = i;
sort(e + 1, e + m + 1);
int ans = 0;
for (int i = 1; i <= m; i++) {
int fx = find(e[i].x), fy = find(e[i].y);
if (fx == fy) continue;
ans++; fa[fx] = fy;
add_edge(e[i].x, e[i].y, e[i].z);
add_edge(e[i].y, e[i].x, e[i].z);
}
}
void dfs(int fr, int val) {
w[fr][0] = val;
for (int i = 1; i < 20; i++)
f[fr][i] = f[f[fr][i - 1]][i - 1], w[fr][i] = max(w[fr][i - 1], w[f[fr][i - 1]][i - 1]);
for (int i = head[fr]; i; i = edge[i].next) {
int ca = edge[i].to;
if (ca == f[fr][0]) continue;
f[ca][0] = fr;
dep[ca] = dep[fr] + 1;
dfs(ca, edge[i].dis);
}
}
int lca(int fr, int to) {
if (dep[fr] < dep[to]) swap(fr, to);
int maxx = 0;
for (int i = 0; i < 20; i++)
if (((dep[fr] - dep[to]) >> i) & 1)
maxx = max(maxx, w[fr][i]), fr = f[fr][i];
if (fr == to) return maxx;
for (int i = 19; i >= 0; i--)
if (f[fr][i] != f[to][i])
maxx = max(maxx, max(w[fr][i], w[to][i])), fr = f[fr][i], to = f[to][i];
return max(max(w[to][0], w[fr][0]), maxx);
}
int main(int argc, char const *argv[]) {
scanf("%d%d", &n, &m);
for (int i = 1; i <= m; i++) scanf("%d%d%d", &e[i].x, &e[i].y, &e[i].z);
kruskal();
for (int i = 1; i <= n; i++) f[i][0] = i;
for (int i = 1; i <= n; i++)
if (i == fa[i])
dfs(i, 0);
scanf("%d", &q);
while (q--) {
scanf("%d%d", &a, &b);
if (find(a) != find(b)) puts("impossible");
else printf("%d\n", lca(a, b));
}
return 0;
}