题目链接:http://poj.org/problem?id=1330
题意:
有一棵树,n个结点n-1条边,给你这几条边的信息,再给你两个点,求这两个点的LCA(最近公共祖先)
题解:
一道小题,直接用Tarjan就水过去了,注意细节!
代码:
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int size = 3e5+5;
vector<int> tree[size];
int n, qa, qb, deg[size], vis[size], root;
int fath[size];
int get(int x) {
if(fath[x] == x) return fath[x];
return fath[x] = get(fath[x]);
}
void Unionset(int x, int y) {
int fx = get(x), fy = get(y);
if( fx == fy ) return ;
fath[fy] = fx;
}
void init() {
for ( int i = 0; i <= n; i ++ ) fath[i] = i;
}
int ans = 0;
void Tarjan(int rt) {
for ( int i = 0; i < tree[rt].size(); i ++ ) {
Tarjan(tree[rt][i]);
Unionset(rt, tree[rt][i]);
}
vis[rt] = 1;
if(rt == qa) {
if(vis[qb]) {
ans = get(qb);
return ;
}
}
if(rt == qb) {
if(vis[qa]) {
ans = get(qa);
return ;
}
}
}
int main() {
// freopen("1330.in","r",stdin);
int tst;
scanf("%d", &tst);
while(tst--){
memset(deg, 0, sizeof(deg));
memset(vis, 0, sizeof(vis));
scanf("%d",&n);
init();
for ( int i = 0; i <= n; i ++ ) tree[i].clear();
for ( int i = 0; i < n-1; i ++ ) {
int u, v;
scanf("%d %d", &u, &v);
tree[u].push_back(v); // 有向边
deg[v] ++;
}
// 找树根
for ( int i = 1; i <= n; i ++ ) {
if(deg[i] == 0) {
root = i;
break;
}
}
scanf("%d %d", &qa, &qb);
Tarjan(root);
printf("%d\n", ans);
}
return 0;
}