LCA(最小公共祖先节点问题)POJ1330

//Tarjan算法求LCS(树中的最小公共祖先节点)(离线)
//if node 被标记过,说明节点已经被探索过,所以节点路径已经形成
//先把子树的query解决,只有把子树的儿子节点访问完毕才回溯并查集
#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int maxn = 1e4 +15;
vector<int> Grape[maxn],q[maxn];
bool rudu[maxn];//judge 是否是入度是否为0 if 0 则 root
bool vis[maxn];
int node1,node2,T,n;
int merage[maxn];//缩点
int find(int node)
{
    if(node!=merage[node])
        merage[node] = find(merage[node]);
    return merage[node];
}
int ans;
void Tarjan(int u)//返回LCS
{
    for(int i=0;i!=Grape[u].size();++i)
    {
        int v = Grape[u][i];
        Tarjan(v);
        merage[v] = u;
    }
    vis[u] = true;
    for(int j=0;j!=q[u].size();++j)
    {
        int v = q[u][j];
        if(vis[v])
        {
            ans =  find(v);
            return;
        }
    }
}
int main()
{
    cin>>T;
    while(T--)
    {
        cin>>n;
        for(int i=1;i<=n;++i)
        {
            Grape[i].clear();
            q[i].clear();
        }
        memset(rudu,false,sizeof(rudu));
        memset(vis,false,sizeof(vis));
        for(int i=1;i<=n;++i)
            merage[i] = i;
        int u,v;
        for(int i=0;i!=n-1;++i)
        {
            cin>>u>>v;
            Grape[u].push_back(v);
            rudu[v] = true;
        }//构建树
        int root;
        for(int i=1;i<=n;++i)
            if(!rudu[i])
                root = i;
        cin>>node1>>node2;
        q[node1].push_back(node2);
        q[node2].push_back(node1);
        cout<<ans<<endl;
    }
}

 

posted on 2019-09-25 21:31  chengyulala  阅读(158)  评论(0编辑  收藏  举报

导航