【LCA】0.1单组不会倍增的暴力的树上最近公共祖先

0.1就是0.1……弱的不行……只是暂时存一下为以后高大上的正解作铺垫

Q:LCA都不会你学什么OI?

A:我学不了OI了我要滚粗……

适当解释:

第一行输入点数n以及两个要查询的点q1,q2

第二行输入每个点父亲father[i]

一行输出ans==最近公共祖先……

不会倍增……写了个看起来是正解其实是暴力的东东……

#include<iostream>
#include<cstdlib>
#include<cstdio>
using namespace std;
int father[500];
int q1,q2,h1,h2,n,t1,t2,ans,s1,s2,jump;
bool flag;
bool pd(int q1,int q2)
{
    if (father[q1]==q2) {ans=q2;flag=false;return false;}
    if (father[q2]==q1) {ans=q1;flag=false;return false;}
    if (q1==q2) {ans=q1;flag=false;return false;}
    return true;
}
int main()
{
    cin>>n>>q1>>q2;
    for (int i=1;i<=n;i++) cin>>father[i];
    t1=q1;t2=q2;
    while (t1!=0) {t1=father[t1];h1++;}
    while (t2!=0) {t2=father[t2];h2++;}

    int gap=abs(h1-h2);
    if (h1<h2)
        {
            while (gap>0)
            {
                q2=father[q2];
                gap--;
            }
        }
    else
        {
            while (gap>0)
            {
                q1=father[q1];
                gap--;
            }
        }
    pd(q1,q2);
    flag=true;
    while (q1!=q2)
    {
        s1=q1;s2=q2;jump=233;
        while ((q1!=0)&&(q2!=0)&&(jump>0) )
            {
                q1=father[q1];
                q2=father[q2];
                jump--;
            }
    }
    q1=s1;q2=s2;
    while ( (q1!=0) && (q2!=0) && (pd(q1,q2)) && flag)
    {
        if (flag==false) break;
        q1=father[q1];
        q2=father[q2];
    }
    cout<<"ans=="<<ans<<endl;
    return 0;

}

我一直觉得 && (pd(q1,q2)) 写得真TM好…………我这么弱居然写出了这么强大的东西…………(hzwer:那你要flag干嘛?我:囧)

时间: 2024-08-13 01:25:49

【LCA】0.1单组不会倍增的暴力的树上最近公共祖先的相关文章

树上最近公共祖先(LCA)的算法

有错请大力指出[鞠躬]第一次写正经博客非常慌张 LCA(Least Common Ancestors),即最近公共祖先,是指在有根树中,找出某两个结点u和v最近的公共祖先. 对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大. 另一种理解方式是把T理解为一个无向无环图,而LCA(T,u,v)即u到v的最短路上深度最小的点. --百度百科 LCA的四种算法: 记录dfs序转化为rmq问题(st表) tarjan算法 倍增算法 树链剖

最近公共祖先 LCA 倍增算法

倍增算法可以在线求树上两个点的LCA,时间复杂度为nlogn 预处理:通过dfs遍历,记录每个节点到根节点的距离dist[u],深度d[u] init()求出树上每个节点u的2^i祖先p[u][i] 求最近公共祖先,根据两个节点的的深度,如不同,向上调整深度大的节点,使得两个节点在同一层上,如果正好是祖先结束,否则,将连个节点同时上移,查询最近公共祖先. void dfs(int u){ for(int i=head[u];i!=-1;i=edge[i].next){ int to=edge[i

【原创】洛谷 LUOGU P3379 【模板】最近公共祖先(LCA) -&gt; 倍增

P3379 [模板]最近公共祖先(LCA) 题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每行包含两个正整数x.y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树). 接下来M行每行包含两个正整数a.b,表示询问a结点和b结点的最近公共祖先. 输出格式: 输出包含M行,每行包含一个正整数,依次为每一个询问的结果. 输入输出样例 输入

用“倍增法”求最近公共祖先(LCA)

1.最近公共祖先:对于有根树T的两个结点u.v,最近公共祖先LCA(T,u,v)表示一个结点x,满足x是u.v的祖先且x的深度尽可能大.2.朴素算法:记录下每个节点的父亲,使节点u,v一步一步地向上找父亲,直到找到相同的“祖先”,即 是所求的答案,时间复杂度O(n).3.优化算法(倍增法):利用二进制的思想,想办法使一步一步向上搜变成以2^k地向上跳. 所以定义一个P[][]数组,使p[i][j]表示节点i的2^j倍祖先,因此p[i][0]即为i的父亲. 我们可以得到一个递推式p[i][j]=p

树,LCA,最近公共祖先,倍增

最近公共祖先, 树上倍增,LCA, fa [ i ] [ j ] 表示 i 节点向上 2j 的祖先 很像dp, k 属于 [ 1 , log ( n ) ] ,f [ x ][ k ] = f [ f [ x ] [ k-1 ]] [k-1] 算lca时, 先不妨设 d [ x ] >= d [ y ] 二进制拆分 尝试从x 向上走 k = 2log (n),~~,21,20, 检查到的点是否比 y 深 每次检查中,若是,x= f [ x ] [ k ] 若仍未相会, 即 f [ x ] [ k

[luogu3379]最近公共祖先(树上倍增求LCA)

题意:求最近公共祖先. 解题关键:三种方法,1.st表 2.倍增法 3.tarjan 此次使用倍增模板 #include<cstdio> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<cmath> using namespace std; typedef long long ll; int n,m,root,cnt

lca(最近公共祖先(在线)) 倍增法详解

转自大佬博客 : https://blog.csdn.net/lw277232240/article/details/72870644 描述:倍增法用于很多算法当中,通过字面意思来理解 LCA是啥呢  在一棵树当中 lca表示的是两个节点最近公共祖先, 大家看这课树哈节点5 ,3的lca就是1,13和11的LCA就是6.节点8,12的lca就是8,那么我们如何通过被增来实现LCA呢. 首先请大家认真看下面的分析. depth[x],表示x节点的深度. 大家看下这个数组 grand[x][i] ,

P3379 【模板】最近公共祖先(LCA)(倍增LCA)

题目链接:https://www.luogu.org/problem/P3379 题目大意: 给一棵以s为根的无向树,回答m个询问,回答出a和b最近的公共祖先. 解题报告: 倍增LCA的模板题,用一个数组 f [i] [j]表示i结点的第$2^{j}$个祖先.显然,一个点的祖先是f[i][0],对于当前点的第$2^{j}$个祖先的第$2^{j}$个祖先,等于当前点的第$2^{j+1}$个祖先,因为$2^{j}+2^{j}=2^{j+1}$.所以有递推式$f[i][j]=f[f[i][j-1]][

LCA 在线倍增法 求最近公共祖先

第一步:建树  这个就不说了 第二部:分为两步  分别是深度预处理和祖先DP预处理 DP预处理: int i,j; for(j=1;(1<<j)<n;j++) for(int i=0;i<n;++i) if(fa[i][j]=-1) fa[i][j]=fa[fa[i][j-1]][j-1];/*DP处理出i的2^j祖先是谁*/ 深度预处理: 1 void dfs(int now,int from,int deepth) 2 { 3 deep[now]=deepth; 4 for(i