求LCA可以用tarjan算法(见代码); 这里不详细介绍了。用到的东西主要是dfs + 并查集。 详见最下面的代码。
还有一种方法是利用 倍增的思想 求。
具体就是:
f[i][j] 表示i的第2^j次方个祖先是谁。 则f[i][j]= f[ f[i][j-1] ][j-1]; (j>0) f[i][j]=father[i];(j==0)
这样可以处理出每个节点的2^j次方的祖先是谁。然后对于每个询问p和q的LCA是谁。我们先考虑一种简单的情况:p和q在树的同一层(设为h)。让j>=log(h); 然后比较f[p][j]与f[q][j]是否相等,如果不等,则LCA(p,q)肯定在更高的层上。令p=f[p][j],q=f[q][j]; j--; 如果相等,j--; 这样用类似于二分的方法,可以求出LCA;
如果p和q不在同一层,假设h(p) > h(q); 可以先求出与q在同一层的p的祖先,然后用上面的办法求LCA。 怎么求与q在同一层的p的祖先呢? 可以用二分的方法来求。
for (log = 1; 1 << log <= h[p]; log++); log--; for (i = log; i >= 0; i--) if(h[p] - (1 << i) >= h[q]) p