P3806 模板 點分治1 (點分治小結 )

2021-09-27 08:43:10 字數 1532 閱讀 2966

分治點既然是分治,我們肯定每一次都要選擇乙個點,從他開始分治下去。那麼考慮我們如何選擇這個點呢?我們發現,每一次處理完乙個點之後,我們都要遞迴進它的子樹,那麼時間複雜度受到它最大的子樹的大小的影響。比如,如果原樹是一條鏈,我們選擇鏈首,一路遞迴下去,時間複雜度毫無疑問是o(

實際上,一棵樹的最大子樹最小的點有乙個名稱,叫做重心。

來自:

找重心很簡單,推薦直接看後面的**。

對於一顆樹,求出任意兩點間的距離,兩點有三種選擇:

左子樹乙個點,右子樹乙個點

兩個點都在左子樹

兩個點都在右子樹

很明顯,第一種我們可以通過兩點到根節點的距離之和可以得到兩點間的距離。

個人對點分治的理解就是,求出每個根節點左子樹中任一點到右子樹中任一點的距離(本人蒟蒻,勿噴)。

點分治部分**:

void getdis(int u, int fa, int w)

}void pika(int u, int w, int opt) }}

void divide(int u)

}

getdis()函式,求每個點到根節點的距離,並記錄在d陣列裡面。

pika()函式,opt == 1統計該棵樹中任意兩點到根節點的距離之和。opt == -1 去掉屬於同一子樹間兩點到根節點的距離之和

**:

//

#includeusing namespace std;

const int n = 1e4+10;

const int inf = 1e9+10;

int n, m, k, ans[10000001];

int head[n], tot;

int rt, mi = inf, sz[n], size;

int d[n], vis[n], cnt = 0;

struct edgee[n<<1];

void addedge(int u, int v, int w);

head[u] = tot++;

}//找重心, 最大子樹最小

void getroot(int u, int fa)

mxson = max(mxson, size - sz[u]);

if(mxson < mi)

}void getdis(int u, int fa, int w)

}void pika(int u, int w, int opt) }}

void divide(int u)

}int main()

size = n, mi = inf;

getroot(1, 0);

divide(rt);

for(int i = 1; i <= m; i++)

return 0;

}

洛谷 P3806 模板 點分治1 點分治

傳送門 點分治!點分治.滾,雖然也沒有可以講的扣就完事了理解好就行 這裡講一下自己計算答案時的乙個部分,我們設tti tt i tti 表示到當前重心的距離為i ii的路徑是否存在 對於每個詢問q iq i qi 因為我們便利完前面的i 1 i 1i 1棵子樹,所以用ttq i itt ttqi i...

洛谷P3806 模板 點分治1 點分治

感謝hzwer的點分治互測。給定一棵有n個點的樹 詢問樹上距離為k的點對是否存在。輸入格式 n,m 接下來n 1條邊a,b,c描述a到b有一條長度為c的路徑 接下來m行每行詢問乙個k 輸出格式 對於每個k每行輸出乙個答案,存在輸出 aye 否則輸出 nay 不包含引號 輸入樣例 1 複製2 1 1 ...

P3806 模板 點分治1

給定一棵有 n 個點的樹,詢問樹上距離為 k 的點對是否存在。關於點分治具體內容可以看這個 這裡主要是詳細講講 getrt是用來求重心,我們利用樹型dp的思維來做,即找到該節點所有的子樹,找到最大的哪一顆即可 void getrt int u,int pa 求重心 maxp u max maxp u...