题目描述 Description
大家都知道,sheep有两只可爱的宠物(一只叫神牛,一只叫神菜)。有一天,sheep带着两只宠物到狗狗家时,这两只可爱的宠物竟然迷路了……
狗狗的家因为常常遭到猫猫的攻击,所以不得不把家里前院的路修得非常复杂。狗狗家前院有N个连通的分叉结点,且只有N-1条路连接这N个节点,节点的编号是1-N(1为根节点)。sheep的宠物非常笨,他们只会向前走,不会退后(只向双亲节点走),sheep想知道他们最早什么时候会相遇(即步数最少)。
输入描述 Input Description
第1行:一个正整数N,表示节点个数。
第2~N行:两个非负整数A和B,表示A是B的双亲。(保证A,B<=n)
第N+1行:两个非负整数A和B,表示两只宠物所在节点的位置。(保证A,B<=n)
输出描述 Output Description
输出他们最早相遇的节点号。
样例输入 Sample Input
10
1 2
1 3
1 4
2 5
2 6
3 7
4 8
4 9
4 10
3 6
样例输出 Sample Output
1
【分析】
N个节点,N-1条边,那就是树了…
题目意思就是要找最近公共祖先,裸啊。
倍增法求LCA,不过数据太水,暴力遍历也可以…
我预处理的时间就够暴力做的了…我想我应该是脑子坏掉了。
主要还是让大家看倍增求LCA。
【代码】
//codevs 1503 stupid pet
#include<iostream>
#include<cmath>
#include<cstdio>
#include<vector>
#define fo(i,j,k) for(i=j;i<=k;i++)
using namespace std;
vector <int> f[1000001];
int fa[1000001][26];
int dep[1000001];
int n,s,e;
bool vis[1000001];
bool flag=0;
inline void dfs(int u,int father,int p)
{
int i,j;
if(flag) return;
if(fa[u][0]==0) dep[u]=0;
else dep[u]=dep[father]+1;
if(u==p)
{
flag=1;
return;
}
int l=f[u].size()-1;
fo(i,0,l)
{
int v=f[u][i];
dfs(v,u,p);
}
}
inline int lca(int x,int y)
{
int i,j,k;
fo(i,1,n)
fo(j,1,25)
fa[i][j]=fa[fa[i][j-1]][j-1];
if(dep[x]<dep[y])
{
int tmp=x;
x=y;
y=tmp;
}
for(i=25;i>=0;i--)
if(dep[y]<=dep[x]-(1<<i))
x=fa[x][i];
if(x==y) return x;
for(i=25;i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int main()
{
int m=0,i,j,k,x,y;
scanf("%d",&n);
fo(i,1,n-1)
{
scanf("%d%d",&y,&x);
fa[x][0]=y;
f[y].push_back(x);
vis[x]=1;
}
scanf("%d%d",&s,&e);
fo(i,1,n)
if(!vis[i]) break;
flag=0;
dfs(i,0,s);
flag=0;
dfs(i,0,e);
printf("%d\n",lca(s,e));
return 0;
}