zstu_oj4395: 大家+lca求树上a,b两点最短路经过的最大值
题目链接:4395: 大家
题解:平常我们求lca有有数据f[i][v]表示是v往上方走pow(2,i)步的点,我们也可以用mx[i][v]表示是v往上方走pow(2,i)步的点所经过的最大值
转移方程见代码
#include<bits/stdc++.h>
#include<set>
#include<cstdio>
#include<iomanip>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#define pb push_back
#define mk make_pair
#define ll long long
#define fi first
#define se second
#define PI 3.14159265
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define eps 1e-7
#define pii pair<int,int>
#define pll pair<ll,ll>
typedef unsigned long long ull;
const int mod=998244353;
const ll inf=0x3f3f3f3f3f3f3f;
const int maxn=2e4+5;
using namespace std;
int n,m,ma,f[20][maxn];
int a[maxn],mx[20][maxn],dep[maxn];
vector<int>g[maxn];
void dfs(int v,int fa)
{
for(int i=1;i<20;i++)
{
f[i][v]=f[i-1][f[i-1][v]];
mx[i][v]=max(mx[i-1][f[i-1][v]],mx[i-1][v]);
}
for(int i=0;i<g[v].size();i++)
{
int to=g[v][i];
if(to!=fa){
dep[to]=dep[v]+1;
f[0][to]=v;
mx[0][to]=a[v];
dfs(to,v);
}
}
}
int lca(int x,int y)
{
if(dep[x]<dep[y])swap(x,y);
int t=dep[x]-dep[y],dx=0,dy=0;
for(int k=0;k<20;k++)
{
if(t>>k&1)
{
dx=max(dx,mx[k][x]);x=f[k][x];
}
}
if(x==y)
{
ma=dx;return x;
}
for(int i=19;i>=0;i--)
{
if(f[i][x]!=f[i][y])
{
dx=max(dx,mx[i][x]);x=f[i][x];
dy=max(dy,mx[i][y]);y=f[i][y];
}
}
ma=max(dx,dy);
ma=max(ma,a[f[0][x]]);
return f[0][x];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m;
for(int i=0;i<n-1;i++)
{
int x,y;
cin>>x>>y;g[x].pb(y);g[y].pb(x);
}
for(int j=1;j<=n;j++)cin>>a[j];
dfs(1,0);
while(m--)
{
int x,y;
cin>>x>>y;ma=0;
if(dep[x]<dep[y])swap(x,y);
if(x==y)
{
cout<<a[x]<<endl;
}
else if(lca(x,y)!=y)
{
cout<<-1<<endl;
}
else
{
cout<<max(ma,a[x])<<endl;
}
}
return 0;
}

浙公网安备 33010602011771号