http://poj.org/problem?id=1330
裸LCA
tarjian离线:
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
const int N = 1e4 + 5;
vector<int> g[N];
vector<int> r[N];
int fa[N], vis[N], rt[N], ans, n;
void init()
{
memset(vis,0,sizeof(vis));
memset(rt,0,sizeof(rt));
for(int i = 1;i <= n;i ++)
{
fa[i] = i;
g[i].clear();
r[i].clear();
}
}
int Find(int k)
{
if(k != fa[k])
fa[k] = Find(fa[k]);
return fa[k];
}
//tarjian 离线
void tarjian(int x)
{
//深搜x的所有儿子
for(int i = 0;i < g[x].size();i ++)
{
int son = g[x][i];
tarjian(son);
//标记上它的父节点
fa[son] = x;
}
//标记已经搜过
vis[x] = 1;
//开始遍历关于x的所有关系
for(int i = 0;i < r[x].size();i ++)
{
int t = r[x][i];
//如果x的关系种的另一个也搜过了 就直接向上找他们的公共父节点
if(vis[t])
{
ans = Find(t);
return ;
}
}
}
int main()
{
int T;
cin >> T;
while(T --)
{
cin >> n;
init();
int x, y;
for(int i = 1;i < n;i ++)
{
//x 为父结点
cin >> x >> y;
g[x].push_back(y);
//标记有父结点的子结点 为了找到根结点
rt[y] ++;
}
//只有一组询问
cin >> x >> y;
//相互加入关系表
r[x].push_back(y);
r[y].push_back(x);
for(int i = 1;i <= n;i ++)
{
//从根节点开始tarjian
if(!rt[i])
{
tarjian(i);
}
}
cout << ans << endl;
}
return 0;
}