题意:
给你一个图, q 个查询, 每个查询输出两点之间 的路径中 最大值的最小值。
思路:
要想路径最大值最小, 边肯定在最小生成树上。
先把图建成最小生成树。
那么问题就是 输出树上两点之间的 边权最大值。
赤裸裸的树剖。
可惜比赛时脑残没有想到 最小生成树。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 50000 + 7;
const int maxt = 100000 + 7;
const int inf = 0x3f3f3f3f;
vector<pair<int,int> >g[maxn];
int fa[maxn];
struct Edge{
int u, v, w;
void read(){
scanf("%d %d %d", &u, &v, &w);
}
}e[maxt];
bool cmp(Edge a, Edge b){
return a.w < b.w;
}
int find(int x){
return fa[x] == x ? fa[x] : fa[x] = find(fa[x]);
}
int siz[maxn];
int son[maxn];
int pre[maxn];
int id[maxn];
int fid[maxn];
int deep[maxn];
int top[maxn];
int D[maxn];
int uzi;
void dfs(int cur,int f,int dep){
pre[cur] = f;
siz[cur] = 1;
deep[cur] = dep;
for (int i = 0; i < g[cur].size(); ++i){
int v = g[cur][i].first;
int w = g[cur][i].second;
if (v != f){
D[v] = w;
dfs(v, cur, dep+1);
siz[cur] += siz[v];
if (son[cur] == -1 || siz[v] > siz[ son[cur] ]){
son[cur] = v;
}
}
}
}
void getpos(int u,int sp){
top[u] = sp;
id[u] = uzi++;
fid[uzi-1] = u;
if (son[u] == -1)return;
getpos(son[u], sp);
for (int i = 0; i < g[u].size(); ++i){
int v = g[u][i].first;
if (v != pre[u] && v != son[u]){
getpos(v, v);
}
}
}
struct node{
int mx;
}nod[maxn<<2];
void build(int l,int r,int o){
if (l == r){
nod[o].mx = D[fid[l] ];
return;
}
int m = l + r >> 1;
build(l, m, o<<1);
build(m+1, r, o<<1|1);
nod[o].mx = max(nod[o<<1].mx, nod[o<<1|1].mx);
}
int query(int L,int R,int l,int r, int o){
if (L <= l && r <= R){
return nod[o].mx;
}
int m = l + r >> 1;
int ans = 0;
if (m >= L){
ans = max(ans, query(L, R, l, m, o<<1));
}
if (m < R){
ans = max(ans, query(L, R, m+1, r, o<<1|1));
}
return ans;
}
int solve(int u,int v,int n){
int f1 = top[u], f2 = top[v];
int ans = 0;
while(f1 != f2){
if (deep[f1] < deep[f2]){
swap(f1,f2);
swap(u, v);
}
ans = max(ans, query( id[f1], id[u], 1, n, 1 ));
u = pre[f1];
f1 = top[u];
}
if (u == v){
return ans;
}
if (deep[u] > deep[v]){
swap(u, v);
}
ans = max(ans, query(id[ son[u] ], id[v], 1, n, 1));
return ans;
}
int main(){
int n, m;
int ks = 0;
while(~scanf("%d %d",&n, &m)){
for (int i = 1; i <= n; ++i){
g[i].clear();
son[i] = -1;
fa[i] = i;
}
uzi = 0;
for (int i = 0; i < m; ++i){
e[i].read();
}
sort(e, e + m, cmp);
int cnt = 0;
for (int i = 0; i < m; ++i){
int u = e[i].u;
int v = e[i].v;
int w = e[i].w;
if (find(u) == find(v)){
continue;
}
fa[find(u) ] = find(v);
cnt++;
g[u].push_back(make_pair(v, w));
g[v].push_back(make_pair(u, w));
if (cnt == n-1)break;
}
dfs(1, -1, 0);
getpos(1, 1);
D[1] = -inf;
build(1, n, 1);
int q;
scanf("%d",&q);
if (ks++)puts("");
while(q--){
int s, t;
scanf("%d %d",&s, &t);
int ans = solve(s, t, n);
printf("%d\n", ans);
}
}
return 0;
}