Description
给你N个点的无向图 (1 <= N <= 15,000),记为:1…N。
图中有M条边 (1 <= M <= 30,000) ,第j条边的长度为: d_j ( 1 < = d_j < = 1,000,000,000).
现在有 K个询问 (1 < = K < = 20,000)。
每个询问的格式是:A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
Input
第一行: N, M, K。
第2..M+1行: 三个正整数:X, Y, and D (1 <= X <=N; 1 <= Y <= N). 表示X与Y之间有一条长度为D的边。
第M+2..M+K+1行: 每行两个整数A B,表示询问从A点走到B点的所有路径中,最长的边最小值是多少?
Output
对每个询问,输出最长的边最小值是多少。
Sample Input
6 6 8
1 2 5
2 3 4
3 4 3
1 4 8
2 5 7
4 6 2
1 2
1 3
1 4
2 3
2 4
5 1
6 2
6 1
1 2 5
2 3 4
3 4 3
1 4 8
2 5 7
4 6 2
1 2
1 3
1 4
2 3
2 4
5 1
6 2
6 1
Sample Output
5
5
5
4
4
7
4
5
5
5
4
4
7
4
5
HINT
1 <= N <= 15,000
1 <= M <= 30,000
1 <= d_j <= 1,000,000,000
1 <= K <= 15,000
题解
裸的$Kruskal$重构树,当模板码着。
1 //It is made by Awson on 2017.10.8 2 #include <map> 3 #include <set> 4 #include <cmath> 5 #include <ctime> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <cstdio> 10 #include <string> 11 #include <cstdlib> 12 #include <cstring> 13 #include <iostream> 14 #include <algorithm> 15 #define link LINK 16 #define set SET 17 #define find FIND 18 #define LL long long 19 #define Max(a, b) ((a) > (b) ? (a) : (b)) 20 #define Min(a, b) ((a) < (b) ? (a) : (b)) 21 using namespace std; 22 const int N = 15000; 23 const int M = 30000; 24 25 int n, m, k, lim, u, v; 26 struct ss { 27 int u, v, c; 28 bool operator < (const ss &b) const{ 29 return c < b.c; 30 } 31 }link[M+5]; 32 struct tt { 33 int to, next; 34 }edge[(N<<2)+5]; 35 int path[(N<<1)+5], top; 36 int set[(N<<1)+5], pos; 37 int fa[(N<<1)+5][15], c[(N<<1)+5], dep[(N<<1)+5]; 38 39 void add(int u, int v) { 40 edge[++top].to = v; 41 edge[top].next = path[u]; 42 path[u] = top; 43 } 44 int find(int x) { 45 return set[x] ? set[x] = find(set[x]) : x; 46 } 47 void Kruskal() { 48 sort(link+1, link+1+m); 49 int cnt = 0; pos = n; 50 for (int i = 1; i <= m; i++) { 51 int q = find(link[i].u); 52 int p = find(link[i].v); 53 if (p != q) { 54 c[++pos] = link[i].c; 55 add(p, pos); add(q, pos); 56 add(pos, p); add(pos, q); 57 cnt++; 58 set[p] = set[q] = pos; 59 if (cnt == n-1) return; 60 } 61 } 62 } 63 void dfs(int r, int depth) { 64 dep[r] = depth; 65 for (int i = path[r]; i; i = edge[i].next) 66 if (edge[i].to != fa[r][0]){ 67 fa[edge[i].to][0] = r; 68 dfs(edge[i].to, depth+1); 69 } 70 } 71 int lca(int u, int v) { 72 if (dep[u] < dep [v]) swap(u, v); 73 for (int i = lim; i >= 0; i--) 74 if (dep[fa[u][i]] >= dep[v]) u = fa[u][i]; 75 if (u != v) { 76 for (int i = lim; i >= 0; i--) 77 if (fa[u][i] != fa[v][i]) { 78 u = fa[u][i], v = fa[v][i]; 79 } 80 u = fa[u][0], v = fa[v][0]; 81 } 82 return u; 83 } 84 void work() { 85 scanf("%d%d%d", &n, &m, &k); lim = log(n)/log(2); 86 for (int i = 1; i <= m; i++) scanf("%d%d%d", &link[i].u, &link[i].v, &link[i].c); 87 Kruskal(); 88 dfs(pos, 1); 89 for (int t = 1; t <= lim; t++) 90 for (int i = 1; i <= pos; i++) 91 fa[i][t] = fa[fa[i][t-1]][t-1]; 92 while (k--) { 93 scanf("%d%d", &u, &v); 94 printf("%d ", c[lca(u, v)]); 95 } 96 } 97 int main() { 98 work(); 99 return 0; 100 }