1738. Heatwave
题解
先做一遍最小生成树(Kruscal),再求每个询问中两点到他们的LCA的路径上边的最大值。
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define N 15000+10
#define M 40000+10
struct Etype{
int u,v,d;
}E[M];
const int MX=15;
int Node[M],Next[M],D[M],Head[N],tot;
int f[N];
int Fa[N][20],V[N][20],H[N];
int n,m,Q;
bool cmp(Etype a,Etype b) {return a.d < b.d ;}
void Swap(int *a,int *b) {int t=*a; *a=*b; *b=t;}
void link(int u,int v,int w) {
Node[++tot]=v;
D[tot]=w;
Next[tot]=Head[u];
Head[u]=tot;
}
int getfather(int x) {
if(f[x]==x) return x;
return f[x]=getfather(f[x]);
}
void DFS(int F,int x,int depth) {
H[x]=depth;
for(int p=Head[x];p;p=Next[p]) {
if(Node[p]==F) continue;
Fa[Node[p]][0]=x;
V[Node[p]][0]=D[p];
DFS(x,Node[p],depth+1);
}
}
int Lca(int x,int y) {
int ans=0;
if(H[x]<H[y]) swap(x,y);
for(int i=MX;i>=0;i--)
if(H[Fa[x][i]]>=H[y]) {
ans=max(ans,V[x][i]);
x=Fa[x][i];
}
if(x==y) return ans;
for(int i=MX;i>=0;i--) {
if(Fa[x][i]!=Fa[y][i]) {
ans=max(ans,V[x][i]);
ans=max(ans,V[y][i]);
x=Fa[x][i];
y=Fa[y][i];
}
}
ans=max(ans,V[x][0]);
ans=max(ans,V[y][0]);
return ans;
}
int main()
{
scanf("%d%d%d",&n,&m,&Q);
for(int i=1;i<=n;i++) f[i]=i;
for(int i=1;i<=m;i++) {
scanf("%d%d%d",&E[i].u,&E[i].v,&E[i].d);
}
sort(E+1,E+m+1,cmp);
for(int i=1;i<=m;i++) {
int f1=getfather(E[i].u);
int f2=getfather(E[i].v);
if(f1!=f2) {
f[f2]=f1;
link(E[i].u,E[i].v,E[i].d);
link(E[i].v,E[i].u,E[i].d);
}
}
DFS(0,1,1);
for(int k=1;k<=MX;k++) {
for(int i=1;i<=n;i++) {
if(!Fa[Fa[i][k-1]][k-1]) continue;
Fa[i][k]=Fa[Fa[i][k-1]][k-1];
V[i][k]=max(V[i][k-1],V[Fa[i][k-1]][k-1]);
}
}
for(int i=1;i<=Q;i++) {
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",Lca(u,v));
}
return 0;
}