hihocoder 1067(最近公共祖先tarjin)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<vector>
#define MAXN 100050
using namespace std;
map<string,int>id;         //保存名字的标号
vector<int>edge[MAXN];     //邻接表
vector<int>query[MAXN];    //保存含某个名字的所有问题的标号
string  name[MAXN];        //保存名字
string q1[MAXN],q2[MAXN];  //保存每个问题的左右两个名字
int ans[MAXN];
int fa[MAXN];
int name_s=1;


int get_id(string str)
{
    if(!id[str])
    {
        id[str]=name_s;
        name[name_s++]=str;
    }
    return id[str];
}


int Find(int x)
{
    return x==fa[x]?x:fa[x]=Find(fa[x]);
}

void dfs(int loc,int pre)            //前序遍历
{
    fa[loc]=loc;
    for(int i=0;i<edge[loc].size();i++)
        dfs(edge[loc][i],loc);
    for(int i=0;i<query[loc].size();i++)                    //含这个节点(名字)的所有问题
    {
        int j=query[loc][i];
        int tmp=loc==id[q1[j]]? id[q2[j]] : id[q1[j]];      //找当前问题的另一个名字
        if(fa[tmp]==-1)                                     //另一个名字没访问过
            continue;
        ans[j]=Find(tmp);                                   
    }
    fa[loc]=Find(fa[pre]);                                  //合并到当前节点的根节点
    return;
}

int main()
{
    int n;
    string a,b;
    int t1,t2;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        cin>>a>>b;
        t1=get_id(a);
        t2=get_id(b);
        edge[t1].push_back(t2);
    }
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        cin>>q1[i]>>q2[i];
        query[id[ q1[i] ] ].push_back(i);
        query[id[ q2[i] ] ].push_back(i);
    }
    memset(fa,-1,sizeof(fa));
    fa[0]=0;
    dfs(1,0);
    for(int i=1;i<=n;i++)
        cout<<name[ans[i]]<<endl;
    return 0;
}






猜你喜欢

转载自blog.csdn.net/reallsp/article/details/78161636