題意就是求樹上距離小於等於k的點對有多少個
n2的演算法肯定不行,因為1w個點
這就需要分治。可以看09年漆子超的**
本題用到的是關於點的分治。
乙個重要的問題是,為了防止退化,所以每次都要找到樹的重心然後分治下去,所謂重心,就是刪掉此結點後,剩下的結點最多的樹結點個數最小。
每次分治,我們首先算出重心,為了計算重心,需要進行兩次dfs,第一次把以每個結點為根的子樹大小求出來,第二次是從這些結點中找重心
找到重心後,需要統計所有結點到重心的距離,看其中有多少對小於等於k,這裡採用的方法就是把所有的距離存在乙個陣列裡,進行快速排序,這是nlogn的,然後用乙個經典的相向搜尋o(n)時間內解決。但是這些求出來滿足小於等於k的裡面只有那些路徑經過重心的點對才是有效的,也就是說在同一顆子樹上的肯定不算數的,所以對每顆子樹,把子樹內部的滿足條件的點對減去。
最後的複雜度是n logn logn 其中每次快排是nlogn 而遞迴的深度為logn
#include #include #include #include #include #include #include #include #include #define eps 1e-5
#define maxn 11111
#define maxm 55555
#define inf 1000000000
using namespace std;
struct edge
edge[maxm];
int head[maxn], e;
int n, k, vis[maxn], ans, root, num;
void init()
void add(int u, int v, int w)
int mx[maxn], size[maxn], mi, dis[maxn];
void dfssize(int u, int fa) //處理子樹的大小
}}void dfsroot(int r, int u, int fa) //求重心
}void dfsdis(int u, int d, int fa) //求距離
}int calc(int u, int d)
return ret;
}void dfs(int u)
}}int main()
dfs(1);
printf("%d\n", ans);
}return 0;
}
POJ 1741 樹的分治
tree 求樹上兩點最短距離不超過 k 的對數。通過樹的分治的方法,從根節點自上而下開始求其不同子樹上的兩點通過該點的最短距離小於 k 的對數。有兩點需要注意 1.求某節點不同子樹滿足條件的兩點不好直接求。可以通過先求該節點的所有子節點滿足條件的個數,然後減去其子樹內所有滿足條件的點的個數。這個通過...
poj 1741 樹的分治
看了網上各種大神的樹的分治的模板,然後自己敲了乙個。直接上 了,晚上再寫乙個學習筆記,喪心病狂的poj,上次一直跪在vector上,這次覺得不用vector寫了。include include include include include include include define ll lon...
POJ 1741 樹分治入門
include include include include using namespace std const int inf 0x3f3f3f3f const int max 1e4 5 點分治 cursize 樹當前大小 curroot 當前樹的根 son i 節點i的子節點的個數 d i ...