祖孙询问 Lca-Tarjan

给定一棵包含 <span id="MathJax-Span-2" class="mrow"><span id="MathJax-Span-3" class="mi">nn 个节点的有根无向树,节点编号互不相同,但不一定是 <span id="MathJax-Span-5" class="mrow"><span id="MathJax-Span-6" class="mn">1<span id="MathJax-Span-7" class="mo">&sim;<span id="MathJax-Span-8" class="mi">n1∼n。

有 <span id="MathJax-Span-10" class="mrow"><span id="MathJax-Span-11" class="mi">mm 个询问,每个询问给出了一对节点的编号 <span id="MathJax-Span-13" class="mrow"><span id="MathJax-Span-14" class="mi">xx 和 <span id="MathJax-Span-16" class="mrow"><span id="MathJax-Span-17" class="mi">yy,询问 <span id="MathJax-Span-19" class="mrow"><span id="MathJax-Span-20" class="mi">xx 与 <span id="MathJax-Span-22" class="mrow"><span id="MathJax-Span-23" class="mi">yy 的祖孙关系。

输入格式

输入第一行包括一个整数 表示节点个数;

接下来 <span id="MathJax-Span-25" class="mrow"><span id="MathJax-Span-26" class="mi">nn 行每行一对整数 <span id="MathJax-Span-28" class="mrow"><span id="MathJax-Span-29" class="mi">aa 和 <span id="MathJax-Span-31" class="mrow"><span id="MathJax-Span-32" class="mi">bb,表示 <span id="MathJax-Span-34" class="mrow"><span id="MathJax-Span-35" class="mi">aa 和 <span id="MathJax-Span-37" class="mrow"><span id="MathJax-Span-38" class="mi">bb 之间有一条无向边。如果 <span id="MathJax-Span-40" class="mrow"><span id="MathJax-Span-41" class="mi">bb 是 <span id="MathJax-Span-43" class="mrow"><span id="MathJax-Span-44" class="mo">&minus;<span id="MathJax-Span-45" class="mn">1−1,那么 <span id="MathJax-Span-47" class="mrow"><span id="MathJax-Span-48" class="mi">aa 就是树的根;

第 <span id="MathJax-Span-50" class="mrow"><span id="MathJax-Span-51" class="mi">n<span id="MathJax-Span-52" class="mo">+<span id="MathJax-Span-53" class="mn">2n+2 行是一个整数 <span id="MathJax-Span-55" class="mrow"><span id="MathJax-Span-56" class="mi">mm 表示询问个数;

接下来 <span id="MathJax-Span-58" class="mrow"><span id="MathJax-Span-59" class="mi">mm 行,每行两个不同的正整数 <span id="MathJax-Span-61" class="mrow"><span id="MathJax-Span-62" class="mi">xx 和 <span id="MathJax-Span-64" class="mrow"><span id="MathJax-Span-65" class="mi">yy,表示一个询问。

输出格式

对于每一个询问,若 <span id="MathJax-Span-67" class="mrow"><span id="MathJax-Span-68" class="mi">xx 是 <span id="MathJax-Span-70" class="mrow"><span id="MathJax-Span-71" class="mi">yy 的祖先则输出 <span id="MathJax-Span-73" class="mrow"><span id="MathJax-Span-74" class="mn">11,若 <span id="MathJax-Span-76" class="mrow"><span id="MathJax-Span-77" class="mi">yy 是 <span id="MathJax-Span-79" class="mrow"><span id="MathJax-Span-80" class="mi">xx 的祖先则输出 <span id="MathJax-Span-82" class="mrow"><span id="MathJax-Span-83" class="mn">22,否则输出 <span id="MathJax-Span-85" class="mrow"><span id="MathJax-Span-86" class="mn">00。

数据范围

<span id="MathJax-Span-88" class="mrow"><span id="MathJax-Span-89" class="mn">1<span id="MathJax-Span-90" class="mo">&le;<span id="MathJax-Span-91" class="mi">n<span id="MathJax-Span-92" class="mo">,<span id="MathJax-Span-93" class="mi">m<span id="MathJax-Span-94" class="mo">&le;<span id="MathJax-Span-95" class="mn">4<span id="MathJax-Span-96" class="mo">&times;<span id="MathJax-Span-97" class="msubsup"><span id="MathJax-Span-98" class="mn">10<span id="MathJax-Span-99" class="mn">41≤n,m≤4×104,
<span id="MathJax-Span-101" class="mrow"><span id="MathJax-Span-102" class="mn">1<span id="MathJax-Span-103" class="mo">&le;<span id="MathJax-Span-104" class="texatom"><span id="MathJax-Span-105" class="mrow"><span id="MathJax-Span-106" class="mo">每<span id="MathJax-Span-107" class="texatom"><span id="MathJax-Span-108" class="mrow"><span id="MathJax-Span-109" class="mo">个<span id="MathJax-Span-110" class="texatom"><span id="MathJax-Span-111" class="mrow"><span id="MathJax-Span-112" class="mo">节<span id="MathJax-Span-113" class="texatom"><span id="MathJax-Span-114" class="mrow"><span id="MathJax-Span-115" class="mo">点<span id="MathJax-Span-116" class="texatom"><span id="MathJax-Span-117" class="mrow"><span id="MathJax-Span-118" class="mo">的<span id="MathJax-Span-119" class="texatom"><span id="MathJax-Span-120" class="mrow"><span id="MathJax-Span-121" class="mo">编<span id="MathJax-Span-122" class="texatom"><span id="MathJax-Span-123" class="mrow"><span id="MathJax-Span-124" class="mo">号<span id="MathJax-Span-125" class="mo">&le;<span id="MathJax-Span-126" class="mn">4<span id="MathJax-Span-127" class="mo">&times;<span id="MathJax-Span-128" class="msubsup"><span id="MathJax-Span-129" class="mn">10<span id="MathJax-Span-130" class="mn">4
1≤每个节点的编号≤4×104

输入样例:

10
234 -1
12 234
13 234
14 234
15 234
16 234
17 234
18 234
19 234
233 19
5
234 233
233 12
233 13
233 15
233 19

输出样例:

1
0
0
0
2

 

分析

Tarjan 算法 是一种 离线算法,需要使用 并查集 记录某个结点的祖先结点。

当一个节点回溯之后,它和还未被标记有lca且已经回溯过的所有节点的lca,是那个还没回溯,且在那些节点链上深度最低的节点

并查集 实现 找每个节点链上深度最低的点(简称每个节点的根),在每次回溯完之后都更新成它的根节点,然后假如说链长度>2 ,就会实现子子节点的根是子节点,子节点的根是根节点,由于并查集更改了子节点的根,也就同时改变了子子节点的根,变成了根节点。

//#define int ll
const int N = 80010;
int n,m;
int h[N],ne[N],e[N],w[N],idx,p[N];
int root;
int res[N],st[N];
V<pii>query[N];
pii request[N];

void add(int a,int b) {
    e[idx] = b,ne[idx] = h[a],h[a] = idx ++ ;
}

int find(int x) {
    return x == p[x] ? x : p[x] = find(p[x]);
}

void tarjan(int u) {
    st[u] = 1;
    for(int i = h[u];~i;i=ne[i]) {
        if(!st[e[i]]) {
            tarjan(e[i]);
            p[e[i]] = u;
        }
    }
    for(auto item:query[u]) {
        int j = item.x;
        int id = item.y;
        if(st[j] == 2) {//如果两个节点都已经回溯过了
            int fa = find(j);//它们的最近公共祖先就是它们遍历过程中深度最低的点
            res[id] = fa;//
        }
    } 
    st[u] = 2;
}

void solve()
{
//    cin>>n>>m;
    cin>>n;
    ms(h,-1);
    fo(i,1,N) p[i] = i;
    fo(i,1,n) {
        int a,b;cin>>a>>b;
        if(b == -1)root = a;
        else add(a,b),add(b,a);
    }
    cin>>m;
    fo(i,1,m) {
        int a,b;cin>>a>>b;
        query[a].pb({b,i});
        query[b].pb({a,i});
        request[i] = {a,b};
    }
    tarjan(root);
    fo(i,1,m) {
        if(res[i] == request[i].x) puts("1");
        else if(res[i] == request[i].second) puts("2");
        else puts("0");
    }
    rt;
}

signed main(){
    AC();
    clapping();TLE;
//  while(cin>>n,n)
//  while(cin>>n>>m,n,m)
//    int t;cin>>t;while(t -- )
    solve();
//    {solve(); }
    return 0;
}

 

posted @ 2022-08-05 15:13  er007  阅读(40)  评论(0编辑  收藏  举报