2012-10-05 16:28:05Morris

[ZJ][LCA][online] d767. 血緣關係

內容 :

給一張祖譜,詢問 A , B 兩人關係最近的共同祖先 以及 A , B 之間的親等
example 1

親等計算 : 往上算到與要計算的人共同祖先處,再往下算到那個人,數多少就是幾親等。

※ 輸入的人的編號,必為 1~N ,而兒女編號必大於父母本身的編號。

輸入說明 :

第一行兩個數字 N , Q
分別代表接下來會有 N 行數字分別代表該人的兒女編號(以 0 表結束),
再來會有 Q 行
每行上會有兩個數字 A , B ,代表要求出 A , B 兩人的關係最近的共同祖先
以及 A , B 之間的親等。
詳細請參考Sample Input
(N≦3,0000,    1≦A,B≦N,     Q≦N2)

輸出說明 :

輸出兩個數字最近的共同祖先 以及 A , B 之間的親等

範例輸入 :help

7 6
2 3 0
4 5 0
6 7 0
0
0
0
0
4 5
4 2
4 4
4 3
1 7
2 3

範例輸出 :

2 2
2 1
4 0
1 3
1 2
1 2

提示 :

背景知識: RMQ

※ 在此未符合實際事實,暫定一個人的兒女不超過6個

Ranged Minimum/Maximum Query(RMQ)
Least Common Ancestors (LCA)

出處 :

RMQ & LCA (管理:morris1028)

#include <stdio.h>
#include <vector>
#define maxN 32768
using namespace std;
typedef struct {
    int nd, dp;
} ELE;
vector<int> g[maxN];
int lidx[maxN], tidx, M;
ELE tree[maxN<<2], stk[maxN<<1];
void dfs(int nd, int dep) {
    if(!lidx[nd])
        lidx[nd] = tidx;
    stk[tidx].nd = nd, stk[tidx++].dp = dep;
    for(vector<int>::iterator it = g[nd].begin();
        it != g[nd].end(); it++) {
        dfs(*it, dep+1);
        stk[tidx].nd = nd, stk[tidx++].dp = dep;
    }
}
void setTree(int n) {
    for(M = 1; M < n+1; M <<= 1);
    for(int i = 2*M-1; i > 0; i--) {
        if(i >= M)
            tree[i] = stk[i-M];
        else {
            if(tree[i<<1].dp < tree[i<<1|1].dp)
                tree[i] = tree[i<<1];
            else
                tree[i] = tree[i<<1|1];
        }
    }
}
ELE query(int s, int t) {
    static int i;
    ELE ans;
    ans.dp = 0xfffff;
    for(s = s+M-1, t = t+M+1; (s^t) != 1;) {
        if(~s&1) {
            if(ans.dp > tree[s^1].dp)
                ans = tree[s^1];
        }
        if(t&1) {
            if(ans.dp > tree[t^1].dp)
                ans = tree[t^1];
        }
        s >>= 1, t >>= 1;
    }
    return ans;
}
int ReadInt(int *x) {
    static char c, neg;
    while((c = getchar()) < '-')    {if(c == EOF) return EOF;}
    neg = (c == '-') ? -1 : 1;
    *x = (neg == 1) ? c-'0' : 0;
    while((c = getchar()) >= '0')
        *x = (*x << 3) + (*x << 1) + c-'0';
    *x *= neg;
    return 1;
}
int main() {
    int n, q, x, i, j;
    while(scanf("%d %d", &n, &q) == 2) {
        for(i = 1; i <= n; i++) {
            g[i].clear();
            lidx[i] = 0;
            while(ReadInt(&x), x)
                g[i].push_back(x);
        }
        tidx = 0;
        dfs(1, 0);
        setTree(tidx);
        ELE ans;
        while(q--) {
            ReadInt(&i), ReadInt(&j);
            i = lidx[i], j = lidx[j];
            if(i > j)
                x = i, i = j, j = x;
            ans = query(i, j);
            printf("%d %d\n", ans.nd, -2*stk[lidx[ans.nd]].dp+stk[i].dp+stk[j].dp);
        }
    }
    return 0;
}