點分治學習

2022-05-25 18:54:11 字數 1545 閱讀 3769

例題:考慮一顆邊權為1的樹上有多少個路徑正好為k的點對。

我們考慮乙個這樣的樹,現在問,這個樹上有多少個點對之間的距離為k。

首先,我們從根結點開始考慮。

那麼我們可以把所有的路徑劃分為兩個部分

1,經過根結點的路徑。2,不經過根結點的路徑。

對於第一種路徑,經過根節點,那麼就是x->root->y。

也就是說這條路徑是root的兩個不同子樹的鏈組成。

那麼不就是考慮d[x] + d[y] == k的點對嗎。

我們可以求的root到每個結點的距離,存放到d陣列裡面。

同時,儲存每個結點是root的哪個子樹下面的點 用b陣列儲存,儲存root能到那些結點,用point陣列儲存。

那麼我們可以把point陣列根據距離進行排序。

從而用兩個指標的方式將其進行統計。

對於第二種路徑來說,

不就是遞迴第一種路徑嘛。

#include"stdio.h"

#include"string.h"

#include"algorithm"

using namespace std;

inline int read()

while(c>='0'&&c<='9')

return x*f;

}const int n = 100010;

int head[n],ver[n],next[n],edge[n],tot;

int n,m;

int v[n],size[n],ans,root;///找到樹的重心

int vis[n];

int d[n],b[n],point[n],top;

int cnt[n];

int num,k;

void add(int x,int y,int w)

void get_root(int x,int far,int n)

max_part = max(max_part,n - size[x]);

if(max_part < ans || root == 0)

return ;

}void get_dist(int x,int far,int ww,int from)

}int cmp(int x,int y)

void calc(int root)

sort(point + 1,point + top + 1,cmp);

int left = 1,right = top;

while(left < right)

else break;

r --;

}num += xx;

left ++;}}

}void solve(int u)

}int main()

ans = n;

get_root(1,0,n);

solve(root);

printf("%d\n",num);

}

點分治學習

嗯,蒟蒻我剛學的就記錄一下 以洛谷的tree為模板講解 洛谷題目傳送門 了解點分治之前,首先要知道什麼是重心 要用到 簡單來說,就是子樹最小的那個節點,我們需要o n 地找到他來保證複雜度 void get root rg int now,rg int fm num max num,tot size...

點分治學習

嗯,蒟蒻我剛學的就記錄一下 以洛谷的tree為模板講解 洛谷題目傳送門 了解點分治之前,首先要知道什麼是重心 要用到 簡單來說,就是子樹最小的那個節點,我們需要o n 地找到他來保證複雜度 void get root rg int now,rg int fm num max num,tot size...

點分治學習筆記

點分治主要用來處理樹上路徑問題,可以統計樹上點到點的所有路徑,複雜度o nlogn 基於樹上的結點進行分治,不斷將一棵樹拆成多顆子樹處理 選擇點時為了防止退化成鏈的情況,如果選點後左右子樹越大,遞迴層數越多,時間越慢,反之則越快,我們每次選擇子樹內的重心 void getroot int u,int...