http://poj.org/problem?id=1330
题意:单纯求LCA板子
题解:单纯跑LCA
注意:不知道根节点时,用并差集把所有点连起来,最后直接 root=find(1)即可(都懂吧)
初始化并差集的fat数组和vector数组时一定要注意你的范围(点的多少)
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<stdlib.h>
#include<vector>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1000000;
int par[100][10005];//j这个点向上跳2^i个的结点
int dep[10005];//深度
vector<int> G[10005];
int MAXK;//能跳到的步数 2^k
int root;
int fat[10005];
int find(int x){
if(x==fat[x]) return x;
return fat[x]=find(fat[x]);
}
void mix(int x,int y){
int na=find(x);
int nb=find(y);
if(na!=nb){
fat[nb]=na;
}
}
void dfs(int v,int p,int d){
par[0][v]=p;//v这个节点向上跳2^0个就是p
dep[v]=d;
for(int i=0;i<G[v].size();i++){
if(G[v][i]!=p){
// dis[G[v][i].second]=dis[v]+G[v][i].first; //更新距离
dfs(G[v][i],v,d+1);
}
}
}
void init(int V){
dfs(root,-1,0);
for(int k=0;k+1<MAXK;k++){
for(int v=1;v<=V;v++){
if(par[k][v]==-1) par[k+1][v]=-1;
else par[k+1][v]=par[k][par[k][v]];
}
}
}
int lca(int u,int v){
if(dep[u]>dep[v]) //保证每次都是可以从最深的点往上跳
swap(u,v);
for(int k=0;k<MAXK;k++){
if( (dep[v]-dep[u]) >> k & 1){//相当于二进制枚举是1的位置
v=par[k][v];
}
}
if(u==v)
return u;
for(int k=MAXK-1;k>=0;k--){
if(par[k][u]!=par[k][v]){//不是同一层
u=par[k][u];
v=par[k][v];
}
}
return par[0][u];
}
int main(){
int t;
cin>>t;
while(t--){
MAXK=50;//最大跳跃的2^K
int N;
cin>>N;
for(int i=1;i<=N;i++) {
fat[i]=i;
G[i].clear();
}
for(int i=1;i<=N-1;i++){
int x,y;
cin>>x>>y;
mix(x,y);
G[x].push_back(y);
}
root=find(1);//用并差集把所有点连起来,找根节点
init(N);
int xx,yy;
cin>>xx>>yy;
int ans=lca(xx,yy);
cout<<ans<<endl;
}
}