您的位置:首页 > 其它

[LCA模板]POJ1330 Nearest Common Ancestors

2014-08-06 22:44 567 查看
题目链接 : http://poj.org/problem?id=1330
题目大意 :求一颗树的LCA

代码:

/*
POJ 1330 给定一棵树 边的形式为a是b父亲 求LCA
倍增
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <queue>
#include <map>
#include <set>
using namespace std;
#define bit_cnt(x) __builtin_popcount((unsigned)x)
#define foru(i, a, b) for(int i=(a); i<=(b); i++)
#define ford(i, a, b) for(int i=(a); i>=(b); i--)
#define clr(a, b) memset(a, (b), sizeof(a))
typedef long long ll;
const double Pi = 4 * atan(1.0);

inline int readint() {
char c = getchar();
while(!isdigit(c)) c = getchar();
int ret = 0;
while(isdigit(c)) ret = ret * 10 + c - '0', c = getchar();
return ret;
}
/*************************************************************/
const int N = 10010;

int n, a, b, root, tot;
int adj
, aim[2*N], next[2*N];
int anc
[22], dep
;

void add(int a, int b){
tot ++;
aim[tot] = b;
next[tot] = adj[a];
adj[a] = tot;
}

void dfs(int x, int pre){
dep[x] = dep[pre]+1;
int k = adj[x];
while (k){
int tx = aim[k];
dfs(tx, x);
k = next[k];
}
}

int swim(int x, int H){
for(int i = 0; H; i++){
if (H&1) x = anc[x][i];
H >>= 1;
}
return x;
}

int LCA(int x, int y){
if (dep[x] < dep[y]) swap(x, y);
x = swim(x, dep[x] - dep[y]);
if (x == y) return x;
ford(i, 20, 0)
if (anc[x][i] != anc[y][i]) {
x = anc[x][i];
y = anc[y][i];
}
return anc[x][0];
}

int main(){
freopen("POJ1330.txt", "r", stdin);
int T; T = readint();
while (T--){
tot = 0; clr(adj, 0); clr(anc, 0);
n = readint();
foru(i, 1, n-1){
a = readint();
b = readint();
add(a, b);
anc[b][0] = a;
}
foru(i, 1, n) if (! anc[i][0]) {root = i; break;}
anc[root][0] = root; dep[root] = 0; dfs(root, root);
foru(j, 1, 20) foru(i, 1, n)
anc[i][j] = anc[anc[i][j-1]][j-1];
a = readint(); b = readint();
printf("%d\n", LCA(a, b));
}
return 0;
}


Tips:

倍增求LCA:
用acn[i][k]记录在点i处向上跳k层到达的点,预处理anc[i][0]=fa[i],利用anc[i][k] = anc[anc[i][k-1]] [k-1]转移
函数swim(i,x)表示在i点向上跳H层到达的点,位运算按H的低位从高位依次跳实现
函数LCA (a,b)表示求a,b的LCA,先另a,b跳到同一高度,若a == b则已找到LCA
否则找到最小的H使得a == b(从高位到低位,若某一个k有anc[A][k] != anc[B][k],则A,B都跳H层)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: