POJ1330(LCA)

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;
}

猜你喜欢

转载自blog.csdn.net/Soul_97/article/details/81565124