初探點分治

2021-09-20 07:20:49 字數 1281 閱讀 2511

給定一棵數,問樹中長度<=k的簡單路徑有多少條。

如果純dfs的話,時間複雜度是o(n

3)

o(n^3)

o(n3

),必然超時。

於是我們考慮用點分治來做。

主要演算法流程有以下幾步:

求樹的重心(乙個點,其所有的子樹中最大的子樹節點數最少)p;

從p出發進行dfs,將子樹節點存起來並按照權值排序;

進行calc§操作,由於排序後的節點滿足單調性,可以通過二分來求出結果

之前的結果包含了一些共用路徑的,所以遞迴子樹進行操作,減去占用公共邊的結果

#include

#include

#include

#include

#include

using

namespace std;

const

int maxn =

100005

;void

read

(int

&x)while

(s>=

'0'&&s<=

'9')

x *= f;

}int n,k,root,minbalance,ans,tsize,m;

vectorint,

int>

>e[maxn]

;int siz[maxn]

,a[maxn]

;bool vis[maxn]

;vector<

int> dep;

void

getroot

(int x,

int fa)

} maxsubtree =

max(maxsubtree,tsize-siz[x]);

if(maxsubtree}void

dfs(

int x,

int fa)}}

intcalc

(int x,

int w)

return res;

}void

exec

(int x)}}

intmain()

);e[y]

.push_back()

;}tsize = minbalance = n;

getroot(1

,0);

exec

(root)

; cout << ans << endl;

}return0;

}

點分治初探

點分治,適用於樹上的路徑統計問題,本質上是用分治思想優化的暴力。其實學會思想就很簡單了。給定一棵樹和乙個整數 k 求樹上長度為 k 的路徑總數。顯然共有 n n 1 條路徑,暴力統計複雜度過高。考慮路徑情況,發現我們可以將其分為兩類 經過根節點的路徑。不經過根節點的路徑。運用分治思想可以發現,我們可...

點分治 動態點分治

實在拖得太久了。先扔掉資料 分治的核心是盡量把乙個整體分成接近的兩個部分,這樣遞迴處理可以讓複雜度從n 變成nlogn。兩個問題,如何區分和如何算答案。對於第乙個問題,重心,然後就是找重心的方法,兩個dfs,對於第二個問題,對於每個重心算當前塊中每個點到重心的答案,然後由重心分開的塊要把多餘的資訊去...

點分治與動態點分治

點分治一般是用於解決樹上路徑問題。樹的重心 把重心這個點割掉後,使所形成的最大的聯通塊大小最小的點。可以證明重心子樹的大小最大不會超過 n over 2 重心可以通過 dfs 一遍求出。maxsiz x 表示割掉點x後所形成的的最大的聯通塊的大小 void dfs int x,int fa max ...