Z2219. [ABC235E] MST + 1

发布时间 2023-10-11 21:39:35作者: 我微笑不代表我快乐

 

 

先写一发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模板题--货车运输