## bzoj 3732: Network 树上两点边权最值

http://www.lydsy.com/JudgeOnline/problem.php?id=3732

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = 30000 + 20;
struct Edge {
int u, v, w, tonext;
bool operator < (const struct Edge & rhs) const {
return w < rhs.w;
}
} e[maxn], t[maxn];
int first[maxn], num;
void addEdge(int u, int v, int w) {
e[num].u = u, e[num].v = v, e[num].w = w, e[num].tonext = first[u];
first[u] = num++;
}
int tfa[maxn];
int tofind(int u) {
if (tfa[u] == u) return u;
else return tfa[u] = tofind(tfa[u]);
}
const int need = 20;
int mx[maxn][25];
int ansc[maxn][25], deep[maxn], fa[maxn];  //所有只需初始值，不需要初始化。
void init_LCA(int cur) {   //1 << 20就有1048576（1e6）了。
ansc[cur][0] = fa[cur]; //跳1步，那么祖先就是爸爸
if (cur != 1) {
for (int i = first[fa[cur]]; ~i; i = e[i].tonext) {
int v = e[i].v;
if (v == cur) {
mx[cur][0] = e[i].w;
break;
}
}
}
int haha = mx[cur][0];
for (int i = 1; i <= need; ++i) { //倍增思路，递归处理
ansc[cur][i] = ansc[ansc[cur][i - 1]][i - 1];
mx[cur][i] = mx[ansc[cur][i - 1]][i - 1];
mx[cur][i] = max(mx[cur][i], haha);
haha = max(haha, mx[cur][i]);  //上到极限的时候需要取个路经的最大值。
}
for (int i = first[cur]; ~i; i = e[i].tonext) {
int v = e[i].v;
if (v == fa[cur]) continue;
fa[v] = cur;
deep[v] = deep[cur] + 1;
init_LCA(v);
}
}
int LCA(int x, int y) {
int res = 0;
if (deep[x] < deep[y]) swap(x, y); //需要x是最深的
for (int i = need; i >= 0; --i) { //从大到小枚举，因为小的更灵活
if (deep[ansc[x][i]] >= deep[y]) { //深度相同，走进去就对了。就是要去到相等。
res = max(res, mx[x][i]);
x = ansc[x][i];
}
}
if (x == y) return res;
for (int i = need; i >= 0; --i) {
if (ansc[x][i] != ansc[y][i]) { //走到第一个不等的地方，
res = max(res, mx[x][i]);
res = max(res, mx[y][i]);
x = ansc[x][i];
y = ansc[y][i];
}
}
res = max(res, mx[x][0]);
res = max(res, mx[y][0]);
return res; //再跳一步就是答案
}

void work() {
num = 0;
memset(first, -1, sizeof first);
int n, m, k;
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= n; ++i) tfa[i] = i;
for (int i = 1; i <= m; ++i) {
scanf("%d%d%d", &t[i].u, &t[i].v, &t[i].w);
}
sort(t + 1, t + 1 + m);
int sel = 0;
for (int i = 1; i <= m; ++i) {
if (sel == n - 1) break;
int x = tofind(t[i].u), y = tofind(t[i].v);
if (x == y) continue;
sel++;
tfa[y] = x;
}
fa[1] = 1, deep[1] = 0;
init_LCA(1);
//    printf("%d\n", mx[2][1]);
for (int i = 1; i <= k; ++i) {
int u, v;
scanf("%d%d", &u, &v);
printf("%d\n", LCA(u, v));
}
}

int main() {
#ifdef local
freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
work();
return 0;
}
View Code

posted on 2017-08-18 22:24  stupid_one  阅读(263)  评论(0编辑  收藏  举报