Z2219. [ABC235E] MST + 1

先写一发LCA
#include<bits/stdc++.h>
using namespace std;
int n,q,x,y,dep[500005],jump[500005][22];
vector<int>d[500005];
void findep(int p,int f,int dp)
{
dep[p]=dp; //点p的深度为dp
for(int i=0;i<=int(d[p].size()-1);i++)
if(d[p][i]!=f)
{
int pn=d[p][i];
jump[pn][0]=p; //pn向上跳2^0即1步的时候,就是它的父亲点
findep(pn,p,dp+1);
}
return ;
}
int lca(int ix,int iy)
{
if(dep[ix]<dep[iy])
//规定ix是深度较大的点
swap(ix,iy);
for(int i=20;i>=0;i--)
//一定是倒过来循环
if(dep[jump[ix][i]]>=dep[iy])
//如果一直跳在iy的下方,才能跳
ix=jump[ix][i];
if(ix==iy) //如果重合,就出结果了
return ix;
for(int i=20;i>=0;i--)
//又是倒过来循环
if(jump[ix][i]!=jump[iy][i])
//所跳的点,必须是两个不同的点
{
ix=jump[ix][i];
iy=jump[iy][i];
}
return jump[ix][0]; //ix的父亲点即是结果
}
int main()
{
scanf("%d%d",&n,&q);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d",&x,&y);
d[x].push_back(y);
d[y].push_back(x);
}
findep(1,0,1);
for(int i=1;i<=20;i++)
for(int j=1;j<=n;j++)
jump[j][i]=jump[jump[j][i-1]][i-1];
for(int i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
printf("%d\n",lca(x,y));
}
return 0;
}
再改一下,求出树上任两点之间的最长边
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10,M=N*2;
int n,m,q;
struct edge
{
int u,v,w;
bool operator<(const edge &x) const
{
return w<x.w;
}
}ed[N];
int fa[N];
int h[N],e[M],ne[M],w[M],tot;
int f[N][22],g[N][22],dep[N];
int find(int x)
{
if(fa[x]==x)
return x;
return fa[x]=find(fa[x]);
}
void add(int a,int b,int c)
{
e[++tot]=b;w[tot]=c;ne[tot]=h[a];h[a]=tot;
}
void dfs(int x,int FA,int d)
//x表示在哪个点,fa是它父亲点,d是深度
{
dep[x]=d;
f[x][0]=FA;
for(int i=h[x];i;i=ne[i])
{
int j=e[i];
if(j==FA) continue;
g[j][0]=w[i];
dfs(j,x,d+1);
}
}
int get_lca(int a,int b)
{
if(dep[a]<dep[b])
swap(a,b);
//规定a是深度较大的
int ans=0;
for(int i=20;i>=0;i--)
if(dep[f[a][i]]>=dep[b])
{
ans=max(ans,g[a][i]);
a=f[a][i];
}
if(a==b)
return ans;
for(int i=20;i>=0;i--)
if(f[a][i]!=f[b][i])
{
ans=max(ans,max(g[a][i],g[b][i]));
a=f[a][i];
b=f[b][i];
}
return max(ans,max(g[a][0],g[b][0]));
}
signed main()
{
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&ed[i].u,&ed[i].v,&ed[i].w);
sort(ed+1,ed+1+m);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<=m;i++)
{
int a=find(ed[i].u),b=find(ed[i].v);
if(a==b) continue;
fa[a]=b;
add(ed[i].u,ed[i].v,ed[i].w);
add(ed[i].v,ed[i].u,ed[i].w);
}
dfs(1,0,1);
for(int i=1;i<=20;i++)
for(int j=1;j<=n;j++)
{
f[j][i]=f[f[j][i-1]][i-1];
g[j][i]=max(g[j][i-1],g[f[j][i-1]][i-1]);
}
for(int i=1;i<=q;i++)
{
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
int lca=get_lca(a,b);
if(lca>c)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
NOIP模板题--货车运输

浙公网安备 33010602011771号