可以通过 poj 1330
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
/**
1.dfs
2.并査集
3.邻接表(vector、数组模拟)
*/
vector < int > Tree[10009];
vector < int > query[10009];
int t, n;
bool vis[10009];
int root[10009];
int ans[10009];
/**
用一个数组存放答案其实是有些不妥,只适用于每次都是不重复的两个节点的询问,
如果有一个节点询问了两次(例如a,b和a,c)就GG了,需要考虑用其他的形式存放
数据,例如邻接表。
*/
int pre[10009];
int finds(int x)
{
if(pre[x] == x)
return x;
int t = finds(pre[x]);
return pre[x] = t;
}
void dfs(int u)
{
for(int i = 0; i < (int)Tree[u].size(); ++ i)
{
dfs(Tree[u][i]);
pre[Tree[u][i]] = u; ///合并
}
vis[u] = true; ///标记为已访问
for(int i = 0; i < (int)query[u].size(); ++ i)
{
if(vis[query[u][i]])
{
int x = finds(query[u][i]);
ans[u] = x;
ans[query[u][i]] = x;
}
}
}
int main()
{
//freopen("in.txt", "r", stdin);
cin >> t;
while(t--)
{
cin >> n;
memset(vis, false, sizeof(vis));
memset(root, 0, sizeof(root));
memset(ans, 0, sizeof(ans));
for(int i = 1; i <= n; ++ i)
{
pre[i] = i;
}
for(int i = 1; i < n; ++ i)
{
int u, v;
cin >> u >> v;
Tree[u].push_back(v);
root[v]++; ///计算每个节点的入度,最后找到根节点
}
int a, b;
cin >> a >> b;
query[a].push_back(b);
query[b].push_back(a);
for(int i = 1; i <= n; ++ i)
{
if(!root[i]) ///如果是根节点的话dfs
{
dfs(i);
}
}
cout << ans[a] << endl;
for(int i = 1; i <= n; ++ i)
{
Tree[i].clear();
query[i].clear();
}
}
return 0;
}