POJ 1741 Tree (樹的分治)

2021-07-15 07:45:34 字數 1821 閱讀 4332

給定一棵樹,計算長度不超過 k的鏈的個數

樹分治入門題,看著題解刷的

選定乙個點,首先一條鏈要麼在此點的子樹上

要麼這條鏈經過這個點

在子樹上就可以劃分為子問題,然後分治處理

經過這個點的鏈,可以把子樹上的點到根的距離處理出來

然後對這些距離排個序,就能 o(n)統計

選點要選重心,重心的所有子樹大小不超過 n/2

這樣保證分治至少是 logn層的,不會發生退化

#pragma comment(linker, "/stack:102400000,102400000")

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace

std;

typedef pair pii;

typedef

long

long ll;

typedef

unsigned

long

long ull;

typedef

double dbl;

typedef

long

double ldbl;

#define mst(a,b) memset(a,b,sizeof(a))

#define clr(a) mst(a,0)

#define sqr(a) ((a)*(a))

#define pcut puts("--------------------")

const

int maxn=1e4+10;

struct graph

void adde(int _u, int _v, int _w)

};int n,k;

graph g;

int nsiz[maxn];

void solve(int,int&);

void get_size(int,int);

void get_centroid(int,int,int&,int&,int&);

void get_dist(int,int,int,vector

&);int get_ans(vector

&);int main()

int ans=0;

solve(1, ans);

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

}return0;}

vector

dist, temp;

void solve(int u, int &ans)

ans += get_ans(dist);

g.del[c]=1;

for(int e=g.last[c]; ~e; e=g.nxt[e])

}void get_size(int u, int f)

}void get_centroid(int u,int f,int &c,int &tmin, int &tot)

tmax = max(tmax, tot-nsiz[u]);

if(tmaxvoid get_dist(int u,int f,int dept,vector

&vec)

}int get_ans(vector

&vec)

return res/2;

}

poj 1741 Tree 樹的分治

解 文中有,就是把路徑分成經過樹根,和不經過樹根兩類,每次處理經過樹根的,然後剩下的子樹部分可以遞迴處理,如果每次選取樹的重心,那麼可以保證最多遞迴logn層。經過樹根的先排序,然後o n 的複雜度就能算出,那麼每層的複雜度nlogn,最多遞迴logn層,總複雜度nlogn 2 include in...

poj 1741 Tree 樹的分治

求樹上倆結點之間距離小於k的結點對個數 倆個點a,b的公共祖先為c,那麼這倆個點的距離就可以用dis a,c dis b,c 表示,我們可以不斷的處理這樣c,然後計算距離,處理點對,為了使平均效能最好,我們需要找的c為每一棵子樹的重心 需要注意的算點對的時候這種方法成立的條件是倆個點不在同一顆子樹上...

POJ 1741 Tree 樹的分治

題目 題意 給定一棵樹,有n個點和n 1條邊,邊有邊權,給出乙個k,求樹上任意兩點間的最短距離不大於k的個數 思路 看了09年漆子超的 利用分治法,每次找樹的重心,重心即是在當前樹中刪掉此點後,節點數最多的子樹的節點數最小,找到重心後,求其所有子孫到其的距離,然後統計一下兩兩之和不大於k的個數,另外...