边带权的LCA
使用方法:
- 存边请使用链式前向星(head+nxt+ver+val 详见最下)
- 宏定义中的MAXN为点数
- 宏定义中的MAXST为点数以2为底的对数
- 宏定义中的INIT为权值的初值(算路径权值和设为0,路径权值最小值设为INF)
- 宏定义中的max后面为权值转化的函数(路径权值最小值设为min,权值路径和请自己定义)
namespace LCA {
#define max min
#define MAXN 500001
#define MAXST 20
#define INIT 0x7fffffff
int fa_lca[MAXN][MAXST];
int val_lca[MAXN][MAXST];
int dep[MAXN];
int lg[MAXN];
void dfs(int p,int dp,int f,int v) {
dep[p]=dp;
fa_lca[p][0]=f;
val_lca[p][0]=v;
for(int i=1;i<=lg[dp];i++)
fa_lca[p][i]=fa_lca[fa_lca[p][i-1]][i-1],
val_lca[p][i]=max(val_lca[p][i-1],val_lca[fa_lca[p][i-1]][i-1]);
for(int i=head[p];i;i=nxt[i])
if(ver[i]!=f)dfs(ver[i],dp+1,p,val[i]);
}
void init(int a,int n) {
lg[1]=0;
for(int i=2;i<=n;i++)
lg[i]=lg[i/2]+1;
dfs(a,1,a,0);
}
pair<int,int> query(int x,int y) {
int ans=INIT;
while(dep[x]!=dep[y]) {
if(dep[x]>dep[y]) {
ans=max(ans,val_lca[x][lg[dep[x]-dep[y]]]);
x=fa_lca[x][lg[dep[x]-dep[y]]];
}
else {
ans=max(ans,val_lca[y][lg[dep[y]-dep[x]]]);
y=fa_lca[y][lg[dep[y]-dep[x]]];
}
}
if(x==y)return make_pair(x,ans);
for(int i=lg[dep[x]];i>=0;i--)
if(fa_lca[x][i]!=fa_lca[y][i]) {
ans=max(ans,val_lca[x][i]);
x=fa_lca[x][i];
ans=max(ans,val_lca[y][i]);
y=fa_lca[y][i];
}
ans=max(ans,max(val_lca[x][0],val_lca[y][0]));
return make_pair(fa_lca[x][0],ans);
}
#undef max
#undef MAXN
#undef MAXST
#undef INIT
}
int head[500001]={0},nxt[1000001],ver[1000001],val[1000001],tot=0;
void add(int x,int y,int v) {
ver[++tot]=y,val[tot]=v,nxt[tot]=head[x],head[x]=tot;
ver[++tot]=x,val[tot]=v,nxt[tot]=head[y],head[y]=tot;
}