BUPT复试专题—最近公共祖先(2014软院)
题目描述
给出一棵有N个节点的有根树TREE(根的编号为1),对于每组查询,请输出树上节点u和v的最近公共祖先。
最近公共祖先:对于有向树TREE的两个结点u,v。最近公共祖先LCA(TREE u,v)表示一个节点x,满足x是u、v的祖先且x的深度尽可能大。
最近公共祖先:对于有向树TREE的两个结点u,v。最近公共祖先LCA(TREE u,v)表示一个节点x,满足x是u、v的祖先且x的深度尽可能大。
输入
输入数据第一行是一个整数T(1<=T<=100),表示测试数据的组数。
对于每组测试数据:
第一行是一个正整数N(1<=N<=100),表示树上有N个节点。
接下来N-1行,每行两个整数u,v(1<=u,v<=N),表示节点u是v的父节点。
接下来一行是一个整数M(1<=M<=1000),表示查询的数量。
接下来M行,每行两个整数u,v(11<=u,v<=N),表示查询节点u和节点v的最近公共祖先。
对于每组测试数据:
第一行是一个正整数N(1<=N<=100),表示树上有N个节点。
接下来N-1行,每行两个整数u,v(1<=u,v<=N),表示节点u是v的父节点。
接下来一行是一个整数M(1<=M<=1000),表示查询的数量。
接下来M行,每行两个整数u,v(11<=u,v<=N),表示查询节点u和节点v的最近公共祖先。
输出
对于每个查询,输出一个整数,表示最近公共祖先的编号,
样例输入
2
3
1 2
1 3
1
2 3
4
1 2
1 3
3 4
2
2 3
3 4
1
1
3
样例输出
1
1
3
来源
数据量较大,直接上输入输出外挂
#include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<map> #define within(x,a,b) ((unsigned)((x)-(a))<=((b)-(a))) using namespace std; int readint(int *p) { int ch; while(!within(ch=getchar(),'0','9')) if(ch == EOF) return EOF; int rslt = 0; do rslt=rslt*10+(ch-'0'); while(within(ch=getchar(),'0','9')); *p = rslt; return 1; } int println_int(int i) { char s[107], p=0; while(i){ s[p++] = i%10; i/=10; } while(p) putchar('0'+s[--p]); putchar('\n'); } struct tree { int father; int floor; }; map< int,tree > donser; int deal(int m,int n) { int floor_max=max(donser[m].floor,donser[n].floor); int floor_min=min(donser[m].floor,donser[n].floor); int x,y; if(donser[m].floor>donser[n].floor) //x->深的 { x=m;y=n; } else { x=n;y=m; } while(floor_max!=floor_min) { x=donser[x].father; floor_max--; } if(x==y) return y; else { while(x!=y) { x=donser[x].father; y=donser[y].father; } return y; } } int main() { int tes,num,shit; while(~scanf("%d",&tes)) { while(tes--) { readint(&num); //cin>>num; donser[0].father=-1; donser[0].floor=1; num--; while(num--) { int x,y; readint(&x); readint(&y); //cin>>x>>y; donser[y].father=x; donser[y].floor=donser[x].floor+1; } //cin>>shit; readint(&shit); while(shit--) { int m,n; readint(&m); readint(&n); //cin>>m>>n; println_int(deal(m,n)); } } } return 0; }