[BZOJ 3732]Network

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

Sample Output

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\n", c[lca(u, v)]);
 95   }
 96 }
 97 int main() {
 98   work();
 99   return 0;
100 }

 

posted @ 2017-10-08 11:20  NaVi_Awson  阅读(193)  评论(0编辑  收藏  举报