标签:i++ names lse lin ++ lca pac std 领域
有根树在计算机科学工程领域是一个人人熟知的数据结构类型。下面是一个例子。
8->(1,4,5);1->(13,14);4->(6,10);5->(9);6->(7,15);10->(2,11,16);16->(3,12);
在这个图中,每个点都是由{1, 2,...,16}中的某个数字标记的。8号点是树的根。如果x号点在y号点到根的路径上,则x是y的祖先。比如4是16的祖先,10也是。事实上,8,4,10,16都是16的祖先。记住,一个节点本身就是自己的祖先。再比如8,4,6,7是7的祖先。
如果x既是y的祖先也是z的祖先则称x是y和z公共祖先。也就是说8和4都是16和7的公共祖先。
如果x在y和z的所有公共祖先中距离y和z最近,则x是y和z的最近公共祖先。也就是说4是16和7的最近公共祖先而不是8,因为4比8更近。
再举一些例子:节点2和3的最近共同祖先是节点10,节点6和13的最近共同祖先是节点8,节点4和12的最近共同祖先是节点4。在最后一个例子中,如果Y是Z的祖先,那么Y和Z的最近共同祖先是Y。
编写一个程序,找出树中两个不同节点的最近共同祖先。
第一行,N和M表示节点数和询问数,节点编号1至N;
以下N-1行,每行两个整数a和b,表示a是b的父亲节点;
之后M行,每行两个不相同的数,表示询问它们的最近共同祖先。
M行,每行一个数表示对应的询问结果。
16 1
1 14
8 5
10 16
5 9
4 6
8 4
4 10
1 13
6 15
10 11
6 7
10 2
16 3
8 1
16 12
16 7
4
时间:1s 空间:256M
对于 40%的数据:1<=N,M<=3000
对于 100%的数据:1<=N,M<=2×10^5
#include<cstdio> #include<iostream> using namespace std; const int Max=500005; int n,m,x,y,cnt,list[Max],s[Max],d[Max],f[Max],hhh[Max]; int son[Max],c[Max]; struct xo { int to,next; }a[4*Max]; void add(int e,int r){ a[++cnt].to=r; a[cnt].next=list[e]; list[e]=cnt; } inline int read(){ int s=0,w=1; char ch=getchar(); while(ch<‘0‘||ch>‘9‘){ if(ch==‘-‘){ w=-1; } ch=getchar(); } while(ch>=‘0‘&&ch<=‘9‘){ s=s*10+ch-‘0‘; ch=getchar(); } return s*w; } void dfs1(int n,int kkksc03){ s[n]=1; d[n]=d[kkksc03]+1; f[n]=kkksc03; int kkksc04; for(int i=list[n];i;i=a[i].next) { kkksc04=a[i].to; if(kkksc04!=kkksc03) { dfs1(kkksc04,n); s[n]+=s[kkksc04]; if(!son[x]||s[son[n]]<s[kkksc04]){ son[n]=kkksc04; } } } } void dfs2(int n,int kkksc03){ c[n]=kkksc03; if(son[n]){ dfs2(son[n],kkksc03); } else{ return; } int kkksc04; for(int i=list[n];i;i=a[i].next) { kkksc04=a[i].to; if(kkksc04!=f[n]&&kkksc04!=son[n]){ dfs2(kkksc04,kkksc04); } } } int lca(int a,int b){ while(c[a]!=c[b]){ if(d[c[a]]<d[c[b]]){ swap(a,b); } a=f[c[a]]; } return d[a]<d[b]?a:b; } int main(){ int kkksc03; n=read(); m=read(); //kkksc03=read(); for(int i=1;i<=n-1;i++){ x=read(); y=read(); add(x,y); hhh[y]=x; add(y,x); } for(int i=1;i<=n;i++){ if(hhh[i]==0){ kkksc03=i; break; } } dfs1(kkksc03,0); dfs2(kkksc03,kkksc03); while(m--){ x=read(); y=read(); printf("%d\n",lca(x,y)); } return 0; }
标签:i++ names lse lin ++ lca pac std 领域
原文地址:https://www.cnblogs.com/hrj1/p/11230991.html