倍增思想

如图,是一棵树

假设一棵树有nn个节点,开一个数组father[n][logn]father[n][logn]father[i][j]father[i][j]表示第ii个节点的第2j2^j个父亲。当寻找父亲节点时,每次跳2p2^p层,大大降低时间复杂度,显然有2p1+2p1=2p2^{p-1}+2^{p-1}=2^p,于是得到递推式:

father[i][j]=father[fahter[i][j1]][j1]father[i][j]=father[fahter[i][j-1]][j-1]

其实就是2j2^{j}分成两步跳。
由于二进制可以表示任何数字,所以这样的跳跃能到达树上的每一个节点。

寻找父亲节点

我们要寻找ii的第kk个父亲节点,就需要把kk拆成二进制,若kk的第jj位为11,则需要将ii向上倍增2j2^j
代码如下

1
2
3
4
5
6
7
int FindFather(int i,int k)
{
int j;
for(j=0;j<=int(log2(k));j++)
if((1<<j)&k) i=father[i][j];//如果k的第j位是1,那就要把i往上提
return i;
}