1644. 二叉树中的最低公共祖先

1644. 二叉树中的最低公共祖先

1.map中查找没找到:a为一个map :a.find(x) == a.end()
你丑你就多读点书。
但是我好像不丑啊。、

 #include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<unordered_map>
using namespace std;
typedef pair<int,int> PII;
unordered_map<int,int> ma;      //从结点值映射到结点编号
unordered_map<int,int> pre;     //从节点编号映射回结点值
const int N = 10010,M=1010,INF=1e9;
int f[N];       //并查集父节点
int vis[N];     //询问和u结点相关的所有节点时 只有vis过才将其的find设置为LCA
int lson[N],rson[N];    //左孩子 右孩子 。lson[i] rson[i] 分别表示i的左孩子和右孩子
int preorder[N],inorder[N];     //分别表示前序遍历 中序遍历
int ans[N];         //最终的结果
PII a[N];       //记录所有询问
vector<PII> query[N];   //记录所有的询问。query[i] = {j,id} 第id次询问i和j的公共祖先
int n,m;
int pivot = 0;      //用来dfs模拟前序遍历 先根再左子树再右子树 
void dfs(int root,int l,int r) //root表示当前根节点所在位置 l表示当前区间最左边 r表示当前区间最右边
{
    if(l>=r) return;        //说明l==r 中间没有元素 l和r所在结点即当前子树的根节点也是唯一结点 即叶节点
    if(root>l)              //l==root说明左边没有了 没有左子树 
    {
        lson[root] = ma[preorder[++pivot]];
        dfs(lson[root],l,root-1);
    }
    if(root<r)              //r==root说明右边没有了 没有右子树
    {
        rson[root] = ma[preorder[++pivot]];
        dfs(rson[root],root+1,r);
    }
}
int find(int x)
{
    if(x==f[x]) return x;
    return f[x] = find(f[x]);
}
void tarjan(int u)  //基于dfs的tarjan算法
{
    if(lson[u])
    {
        
        tarjan(lson[u]); //先tarjan 访问到叶节点了往上翻才是正确的。
        f[lson[u]] = u;  //再设置
    }
    if(rson[u])
    {
        tarjan(rson[u]); //先tarjan
        f[rson[u]] = u;  //在设置
    }

    for(int i=0;i<query[u].size();i++)  //判断所有的关于u结点的询问
    {
        int v=query[u][i].first,idx=query[u][i].second;  //第idx次询问u v的LCA
        if(vis[v])      //tarjan:只有访问过v结点 v结点的根节点才是u v的LCA
        {
            int parent = find(v);
            ans[idx] = parent;
        }
    }
    vis[u] = 1;         //最后在设置vis。因为是dfs 所以只有结束了关于u的dfs才算访问完 
                        //否则在最前面 如果这个节点还有左右子树 则还会继续向下 这个节点没有访问结束。
}
int main()
{
    cin>>m>>n;
    int id=0;
    for(int i=1;i<=n;i++)
    {
        cin>>inorder[i];    //输入中序遍历序列
        ma[inorder[i]]=++id;    //将中序遍历序列离散化。这样中间全用离散化后的即可
        pre[id] = inorder[i];
    }
    for(int i=1;i<=n;i++)
    {
        cin>>preorder[i];
        f[i] = i;
    }
    int root = ma[preorder[1]]; //root就是根节点在中序遍历中的位置编号

    dfs(root,1,n);  //递归遍历建树
    
    for(int i=1;i<=m;i++)
    {
        int x,y;cin>>x>>y;
        a[i].first=x;
        a[i].second=y;
        if(ma.find(x)==ma.end()||ma.find(y)==ma.end())
            ans[i] = INF;
        else  
        {
            x=ma[x];
            y=ma[y];
            if(x!=y)
            {
                query[x].push_back({y,i});
                query[y].push_back({x,i});
            }
            else ans[i] = x;
        }
    }

    tarjan(root);

    for(int i=1;i<=m;i++)
    {
        int u=a[i].first,v=a[i].second;
        if(ans[i]==INF)
        {
            if(ma.find(u)==ma.end()&&ma.find(v)==ma.end())
                printf("ERROR: %d and %d are not found.\n",u,v);
            else if(ma.find(u)==ma.end())
                printf("ERROR: %d is not found.\n",u);
            else if(ma.find(v)==ma.end())
                printf("ERROR: %d is not found.\n",v);
        }
        else 
        {
            int parent = pre[ans[i]];
            if(parent==u)
                printf("%d is an ancestor of %d.\n",u,v);
            else if(parent==v)
                printf("%d is an ancestor of %d.\n",v,u);
            else printf("LCA of %d and %d is %d.\n",u,v,parent);
        }
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值