这道题,先用kruskal求一遍图中的最大生成树。
然后,倍增求lca,求lca的同时求出边权的最小值。
#include <cstring> #include <cstdio> #include <algorithm> int n, m, cnt, q, t, k; int f[10001], head[100001], p[10001][21], minn[10001][21], deep[10001]; bool vis[10001]; struct node { int x, y, z; }tree[100001]; struct Node { int next, to, val; }edge[100001]; inline void add(int a, int b, int c) { edge[cnt].val = c; edge[cnt].to = b; edge[cnt].next = head[a]; head[a] = cnt++; } inline int father(int a) { return a == f[a] ? a : f[a] = father(f[a]); } inline bool cmp(node a, node b) { return a.z > b.z; } void kruskal() { int i; for(i = 1; i <= m; i++) scanf("%d %d %d", &tree[i].x, &tree[i].y, &tree[i].z); for(i = 1; i <= n; i++) f[i] = i; std::sort(tree + 1, tree + m + 1, cmp); for(i = 1; i <= m; i++) { int fa = father(tree[i].x), fb = father(tree[i].y); if(fa != fb) { f[fa] = fb; add(tree[i].x, tree[i].y, tree[i].z); add(tree[i].y, tree[i].x, tree[i].z); } if(k == n - 1) break; } } void dfs(int i) { int j; vis[i] = 1; for(j = head[i]; j != -1; j = edge[j].next) if(!vis[edge[j].to]) { deep[edge[j].to] = deep[i] + 1; p[edge[j].to][0] = i; minn[edge[j].to][0] = edge[j].val; dfs(edge[j].to); } } void init() { int i, j; for(j = 1; (1 << j) <= n; j++) for(i = 1; i <= n; i++) { p[i][j] = p[p[i][j - 1]][j - 1]; minn[i][j] = std::min(minn[i][j - 1], minn[p[i][j - 1]][j - 1]); } } int lca(int a, int b) { int i, j, ret = 707406378; if(deep[a] < deep[b]) std::swap(a, b); for(i = 0; (1 << i) <= deep[a]; i++); i--; for(j = i; j >= 0; j--) if(deep[a] - (1 << j) >= deep[b]) { ret = std::min(ret, minn[a][j]); a = p[a][j]; } if(a == b) return ret; for(j = i; j >= 0; j--) if(p[a][j] != p[b][j]) { ret = std::min(ret, std::min(minn[a][j], minn[b][j])); a = p[a][j]; b = p[b][j]; } ret = std::min(ret, std::min(minn[a][0], minn[b][0])); return ret; } int main() { int i, j, x1, y1; scanf("%d %d", &n, &m); memset(head, -1, sizeof(head)); //memset(minn, 127 / 3, sizeof(minn)); kruskal(); for(i = 1; i <= n; i++) if(!vis[i]) { deep[i] = 1; dfs(i); } init(); scanf("%d", &q); for(i = 1; i <= q; i++) { scanf("%d %d", &x1, &y1); if(father(x1) != father(y1)) printf("-1\n"); else printf("%d\n", lca(x1, y1)); } return 0; }