點分治模板 (樹中點對距離)

2021-07-11 18:15:10 字數 1541 閱讀 1967

點分治就是在一棵樹中,將每個點分治……

基本概念:

點分治:將一棵無根樹變成有根樹,再分別處理每棵有根子樹。

重心:在一棵樹中,這個點的最大子樹是所有點中最小的。也可以說是刪除該點時,樹內剩下的子樹最大節點數最小

size[i]表示以i為根的子樹節點數量。

如何求重心??求出size,什麼是定義,就怎麼求。一般來說總(不是每次)時間複雜度為o(n)

找重心的**(這裡的**都對應著下面的例題):

void findroot(int x,int fa)

mx[x]=max(mx[x],nn-size[x]);

if (mx[x]int main()

**中的nn即為這個子樹的節點數。

為什麼要找重心??

為了使時間複雜度少,每棵子樹都要盡量小,那麼根一定是重心。

給出一棵帶邊權的樹,問有多少對點的距離<=len

1、對於每個點,找出有多少對經過這個點的點對距離在len內,總(不是每次)o(n),減去在子節點中算重的。

2、刪掉這個點,對於剩下的一堆子樹中再重複做。

為了保證時間複雜度,每次都要找重心。

**:

#include 

#include

#include

#include

#include

#include

#define fo(i,a,b) for(int i=a;i<=b;i++)

#define ll long long

#define n 11000

#define clear(a) memset(a,0,sizeof(a));

using namespace std;

int n,nn,len,m,size[n],mx[n],last[n*10],next[n*10],to[n*10],tot,root,ans;

ll data[n*10];

bool bz[n];

ll deep[n],dep[n];

void putin(int

x,int

y,int z)

void findroot(int

x,int fa)

mx[x]=max(mx[x],nn-size[x]);

if (mx[x]x;

}void getdeep(int

x,int fa)

deep[++tot]=dep[x];

}int calc(int

x) else j--;

}return ans;

}void dg(int

x,int fa)

}int main()

mx[0]=2147483647;nn=n;root=0;findroot(1,0);

dg(root,0);

printf("%d",ans);

}

樹中點對距離(點分治)

給出一棵帶邊權的樹,問有多少對點的距離 len 這是一道點分治的經典題目,可以給點分治的初學者練手。點分治,顧名思義就是把每個點分開了處理答案。假設,目前做到了以x為根的子樹。先求出子樹中每個點到根的距離di s 對於兩個點 i 和 j,如果di si d isj k 那麼 i j 就是乙個合法的點...

點分治入門 樹中點對距離詳(?)解

其中樹最多有10000個點,len maxlongint 這是一道模板題目。對於乙個點x,我們考慮如何求解經過x點的路徑方案數,設為f x 考慮直接從x出發做一遍dfs,算出所有未到過的點到x點的距離,然後排序。設兩個指標,如果length l length r len,那麼length l len...

點分治模板 (例題 樹中點對距離) 待更新 坑

description 給出一棵帶邊權的樹,問有多少對點的距離 len c表示最大兒子的節點的size size表示子樹大小 處理子樹大小 void get size int x,int y 找重心 size r size x 是x上面部分的樹的尺寸,跟x的最大孩子比,找到最大孩子的最小差值節點 v...