2 条题解

  • 0
    @ 2022-4-19 22:40:02

    严禁抄题解,发现后取消成绩

    • 0
      @ 2022-4-6 0:19:20

      数据小就用暴力求就可以了,dfs记录好每个节点的父亲节点。 如果两个节点相等,那么lca就是它们自己。 如果不相等,根据深度来求,深度相等,向上访问父亲节点,直到节点相等。 深度不相等,让大的深度向小的靠拢即可。

      
      int lca(int x,int y)
      {
      	if(x==y) return x;
      	else if(de[x]==de[y]) return lca(fa[x],fa[y]);
      	else if(de[x]<de[y]) return lca(x,fa[y]);
      	else return lca(fa[x],y);
      }
      

      数据过大就用倍增求lca,定义father[i][j]为节点i向上跳2^j次方对应的节点是谁, father[i][j]=father[father[i][j-1]][j-1],从i向上2的j次方转移到,从节点father[i][j-1]继续向上2^j-1。dfs时初始化,father[v][0]=u

      想找到u,v第一个不同祖先的位置,就要保证u,v在同一深度(才能一起往上移动) 所以这个过程分为三部分,预处理找到每个节点深度,把较深的一点移动到较浅一点的高度,两个一起往上移动直到他们的父亲相同

      
      #include<bits/stdc++.h>
      using namespace std;
      int n,de[105],u,v,father[105][8],x,y;//第二维只有8,是因为只有100个节点,2的7次方就已经超过100了
      vector<int> e[105];
      void dfs(int u,int fa)
      {
      	for(int i=0;i<e[u].size();i++)
      	{
      		int v=e[u][i];
      		if(v==fa) continue;
      		de[v]=de[u]+1;
      		father[v][0]=u;//v向上跳一次是u 
      		dfs(v,u);
      	}
      }
      void st()
      {
      	for(int j=1;(1<<j)<=n;j++)
      	{
      		for(int i=1;i<=n;i++)
      		{
      			father[i][j]=father[father[i][j-1]][j-1];
      		}
      	}
      }
      int lca(int u,int v)
      {
      	if(de[u]<de[v]) swap(u,v);//默认u深度大,从u向上走 
      	int h=de[u]-de[v];
      	for(int i=0;i<8;i++)//这里就是先让两个节点深度相同 
      	{
      		if(h&(1<<i))//二进制位存在1,就需要向上跳。例如h是5,也就是101。 
      		{
      			u=father[u][i];
      		}
      	}
      	if(u==v)//节点一样直接输出 
      	{
      		return u;
      	}
      	for(int i=7;i>=0;i--)//倒着往回找,找到第一个不相同的节点 第一个不相同的节点的上一个就是最近公共祖先可画图理解 
      	{
      		if(father[u][i]!=father[v][i])
      		{
      		    u=father[u][i];
                  v=father[v][i];
      		}
      	}
      	return father[u][0];
      }
      int main()
      {
      	ios::sync_with_stdio(false);
      	cin.tie(0);
      	cin>>n;
      	cin>>x>>y;
      	for(int i=1;i<n;i++)
      	{
      		cin>>u>>v;
      		e[u].push_back(v);
      		e[v].push_back(u);
      	}
      	de[1]=1;
      	dfs(1,0);
      	st();
      	cout<<lca(x,y);
      	return 0;
      }
      

      • 1

      【入门】树的公共祖先(LCA)(2)

      信息

      ID
      1164
      时间
      1000ms
      内存
      128MiB
      难度
      5
      标签
      递交数
      18
      已通过
      16
      上传者