题355.lca问题-acwing-Q1636–最低公共祖先
一、题目
二、题解
本题关键在于先建树,然后由于这里是给的节点数据不是编号所以得做一手离散化处理,之后再套lca板子即可。代码如下:
//createTree建BST+tarjan:AC
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int Inf=0x3f3f3f3f;
const int maxn=1e4+1,maxm=2*maxn,maxk=11;
typedef struct Tnode *Position;
typedef Position BinT;
struct Tnode
{
int data;
BinT l,r;
};
int N,M;
int pre[maxn],in[maxn];
int sign[maxn];
unordered_map<int,int> id;
int h[maxn],e[maxm],ne[maxm],idx;
vector<pii> qry[maxn],q;
int d[maxn],fa[maxn][maxk];
int p[maxn],flag[maxn],res[1100];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
BinT createTree(int start,int over)
{
int pos=-1;
for(int i=0;i<N;i++)
{
if(sign[i]) continue;//该节点已经建立过了直接continue起到加速的作用
for(int j=start;j<over;j++)
{
if(in[j]==pre[i])
{
sign[i]=1;
pos=j;
break;
}
}
if(pos!=-1) break;
}
BinT T=new Tnode();
T->data=in[pos];
if(pos>start)
{
T->l=createTree(start,pos);
add(id[T->data],id[T->l->data]),add(id[T->l->data],id[T->data]);
}
else T->l=NULL;
if(pos+1<over)
{
T->r=createTree(pos+1,over);
add(id[T->data],id[T->r->data]),add(id[T->r->data],id[T->data]);
}
else T->r=NULL;
return T;
}
int findRoot(int v)
{
if(p[v]==v) return p[v];
else return p[v]=findRoot(p[v]);
}
void tarjan(int u)
{
flag[u]=1;
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(!flag[j])
{
tarjan(j);
p[j]=u;
}
}
for(auto qq:qry[u])
{
int y=qq.first,id=qq.second;
if(flag[y]==2)
{
int root=findRoot(y);
res[id]=root;
}
}
flag[u]=2;
}
int main()
{
scanf("%d%d",&M,&N);
memset(h,-1,sizeof h);
for(int i=0;i<N;i++)
{
scanf("%d",&pre[i]);
in[i]=pre[i];
}
sort(in,in+N);//想到BST中序遍历序列就是从小到大排的递增序列,所以想到与已知pre和in序列还原二叉树,所以可以用createTree来加快建树而不用insertTnode
for(int i=0;i<N;i++) id[in[i]]=i+1;//离散化
BinT T=createTree(0,N);
for(int i=0;i<M;i++)
{
int u,v;
scanf("%d%d",&u,&v);
q.push_back({u,v});
if(id.count(u)&&id.count(v)&&u!=v)
{
qry[id[u]].push_back({id[v],i}),qry[id[v]].push_back({id[u],i});
}
}
for(int i=1;i<=N;i++) p[i]=i;
tarjan(id[T->data]);
for(int i=0;i<q.size();i++)
{
int u=q[i].first,v=q[i].second;
if(id.count(u)==0&&id.count(v)==0) printf("ERROR: %d and %d are not found.\n",u,v);
else if(id.count(u)==0) printf("ERROR: %d is not found.\n",u);
else if(id.count(v)==0) printf("ERROR: %d is not found.\n",v);
else if(u==v) printf("%d is an ancestor of %d.\n",u,v);
else
{
int pid=res[i];
if(pid==id[u]) printf("%d is an ancestor of %d.\n",u,v);
else if(pid==id[v]) printf("%d is an ancestor of %d.\n",v,u);
else
{
printf("LCA of %d and %d is %d.\n",u,v,in[pid-1]);
}
}
}
}
/*
//insertTnode建BST+倍增lca:超时
#include <bits/stdc++.h>
using namespace std;
const int Inf=0x3f3f3f3f;
const int maxn=1e4+1,maxm=2e4+2,maxk=11;
typedef struct Tnode *Position;
typedef Position BinT;
struct Tnode
{
int data;
BinT l,r;
};
int N,M;
int num[maxn];
unordered_map<int,int> id;
int h[maxn],e[maxm],ne[maxm],idx;
int d[maxn],fa[maxn][maxk];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
BinT insertTnode(int data,BinT T)
{
if(!T)
{
T=new Tnode();
T->data=data;
T->l=NULL;
T->r=NULL;
}
else
{
if(data<T->data)
{
T->l=insertTnode(data,T->l);
}
else
{
T->r=insertTnode(data,T->r);
}
}
return T;
}
void levelOrderTraversal(BinT T)
{
queue<BinT> q;
q.push(T);
while(!q.empty())
{
BinT TempT=q.front();
q.pop();
//cout<<TempT->data<<endl;
if(TempT->l)
{
//cout<<id[TempT->l->data]<<" "<<id[TempT->data]<<endl;
add(id[TempT->l->data],id[TempT->data]),add(id[TempT->data],id[TempT->l->data]);
q.push(TempT->l);
}
if(TempT->r)
{
//cout<<id[TempT->r->data]<<" "<<id[TempT->data]<<endl;
add(id[TempT->r->data],id[TempT->data]),add(id[TempT->data],id[TempT->r->data]);
q.push(TempT->r);
}
}
}
void preOrderTraversal(BinT T)
{
if(!T)
{
return;
}
cout<<T->data<<endl;
if(T->l)
{
add(id[T->l->data],id[T->data]);
preOrderTraversal(T->l);
}
if(T->r)
{
add(id[T->r->data],id[T->data]);
preOrderTraversal(T->r);
}
}
void bfs(int root)
{
memset(d,Inf,sizeof d);
queue<int> q;
q.push(root);
d[0]=0,d[root]=1;
while(!q.empty())
{
int t=q.front();
q.pop();
for(int i=h[t];i!=-1;i=ne[i])
{
int j=e[i];
if(d[j]>d[t]+1)
{
d[j]=d[t]+1;
q.push(j);
fa[j][0]=t;
for(int k=1;k<=maxk-1;k++)
{
fa[j][k]=fa[fa[j][k-1]][k-1];
}
}
}
}
}
int lca(int a,int b)
{
if(d[a]<d[b]) swap(a,b);
for(int k=maxk-1;k>=0;k--)
{
if(d[fa[a][k]]>=d[b])
{
a=fa[a][k];
}
}
if(a==b)
{
return a;
}
for(int k=maxk-1;k>=0;k--)
{
if(fa[a][k]!=fa[b][k])
{
a=fa[a][k];
b=fa[b][k];
}
}
return fa[a][0];
}
int main()
{
BinT T=NULL;
scanf("%d%d",&M,&N);
for(int i=0;i<N;i++)
{
scanf("%d",&num[i]);
id[num[i]]=i+1;
T=insertTnode(num[i],T);
}
memset(h,-1,sizeof h);
levelOrderTraversal(T);
bfs(id[T->data]);
for(int i=0;i<M;i++)
{
int u,v;
scanf("%d%d",&u,&v);
if(id.count(u)==0&&id.count(v)==0) printf("ERROR: %d and %d are not found.\n",u,v);
else if(id.count(u)==0) printf("ERROR: %d is not found.\n",u);
else if(id.count(v)==0) printf("ERROR: %d is not found.\n",v);
else
{
int pid=lca(id[u],id[v]);
if(pid==id[u]) printf("%d is an ancestor of %d.\n",u,v);
else if(pid==id[v]) printf("%d is an ancestor of %d.\n",v,u);
else
{
printf("LCA of %d and %d is %d.\n",u,v,num[pid-1]);
}
}
}
}
*/
//insertTnode建BST+tarjan:超时
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int Inf=0x3f3f3f3f;
const int maxn=1e4+1,maxm=2*maxn,maxk=11;
typedef struct Tnode *Position;
typedef Position BinT;
struct Tnode
{
int data;
BinT l,r;
};
int N,M;
int num[maxn];
unordered_map<int,int> id;
int h[maxn],e[maxm],ne[maxm],idx;
vector<pii> qry[maxn],q;
int d[maxn],fa[maxn][maxk];
int p[maxn],flag[maxn],res[1100];
void add(int a,int b)
{
e[idx]=b,ne[idx]=h[a],h[a]=idx++;
}
BinT insertTnode(int data,BinT T,int fa)
{
if(!T)
{
T=new Tnode();
T->data=data;
add(id[T->data],fa),add(fa,id[T->data]);
T->l=NULL;
T->r=NULL;
}
else
{
if(data<T->data)
{
T->l=insertTnode(data,T->l,id[T->data]);
}
else
{
T->r=insertTnode(data,T->r,id[T->data]);
}
}
return T;
}
int findRoot(int v)
{
if(p[v]==v)
{
return p[v];
}
else
{
return p[v]=findRoot(p[v]);
}
}
void tarjan(int u)
{
flag[u]=1;
for(int i=h[u];i!=-1;i=ne[i])
{
int j=e[i];
if(!flag[j])
{
tarjan(j);
p[j]=u;
}
}
for(auto qq:qry[u])
{
int y=qq.first,id=qq.second;
if(flag[y]==2)
{
int root=findRoot(y);
res[id]=root;
}
}
flag[u]=2;
}
int main()
{
BinT T=NULL;
scanf("%d%d",&M,&N);
memset(h,-1,sizeof h);
for(int i=0;i<N;i++)
{
scanf("%d",&num[i]);
id[num[i]]=i+1;
T=insertTnode(num[i],T,0);
}
for(int i=0;i<M;i++)
{
int u,v;
scanf("%d%d",&u,&v);
q.push_back({u,v});
if(id.count(u)&&id.count(v)&&u!=v)
{
qry[id[u]].push_back({id[v],i}),qry[id[v]].push_back({id[u],i});
}
}
for(int i=1;i<=N;i++)
{
p[i]=i;
}
tarjan(id[T->data]);
for(int i=0;i<q.size();i++)
{
int u=q[i].first,v=q[i].second;
if(id.count(u)==0&&id.count(v)==0) printf("ERROR: %d and %d are not found.\n",u,v);
else if(id.count(u)==0) printf("ERROR: %d is not found.\n",u);
else if(id.count(v)==0) printf("ERROR: %d is not found.\n",v);
else if(u==v) printf("%d is an ancestor of %d.\n",u,v);
else
{
int pid=res[i];
//cout<<pid<<endl;
if(pid==id[u]) printf("%d is an ancestor of %d.\n",u,v);
else if(pid==id[v]) printf("%d is an ancestor of %d.\n",v,u);
else
{
printf("LCA of %d and %d is %d.\n",u,v,num[pid-1]);
}
}
}
}