樹形 點分治 POJ 1741 Tree

2022-09-02 18:45:10 字數 1428 閱讀 7344

通道:

題意:有多少對[u,v]的距離小於k

思路:將無根樹轉化成有根樹進行觀察。滿足條件的點對有兩種情況:兩個點的路徑橫跨樹根,兩個點位於同一顆子樹中。

如果我們已經知道了此時所有點到根的距離a[i],a[x] + a[y] <= k的(x, y)對數就是結果,這個可以通過排序之後o(n)的複雜度求出。然後根據分治的思想,分別對所有的兒子求一遍即可,但是這會出現重複的——當前情況下兩個點位於一顆子樹中,那麼應該將其減掉(顯然這兩個點是滿足題意的,為什麼減掉呢?因為在對子樹進行求解的時候,會重新計算)。在進行分治時,為了避免樹退化成一條鏈而導致時間複雜度變為o(n^2),每次都找樹的重心,這樣,所有的子樹規模就會變的很小了。時間複雜度o(nlog^2n)。

**:

#include #include 

#include

#include

#include

using

namespace

std;

typedef

long

long

ll;const

int max_n = 100007

; struct

node

node (

int _v, int _w, int

_n)

};int

n, k;

inthead[max_n], edgecnt;

node g[max_n

<< 1

];bool

del[max_n];

void

clear()

void add(int u, int v, int

w) int

son[max_n], opt[max_n];

vector

alln;

void dfs(int u,int

fa)

}int getcenter(int

u) }

}return

ans;

}int

tot, d[max_n];

void getdist(int u, int fa, int

w)

}ll calc()

return

ans;

}ll ans;

void work(int

u) del[u] = true

;

for(int i = head[u]; ~i; i =g[i].nxt)

}int

main()

ans = 0

; work(1);

printf(

"%lld\n

", ans);

}return0;

}

view code

POJ1741Tree 樹形dp 樹分治

題目大意 給一棵邊帶權樹,問兩點之間的距離小於等於k的點對有多少個。具體題解看 include include include includeusing namespace std const int maxn 21000 struct node tree maxn head maxn tp max...

POJ 1741 樹的點分治

第一次接觸樹分治。打算今晚學的,先看了一蛤樹的重心怎麼求,之後知道了重心後再來看這道題,這種題是不是啟發式合併也可以?一遍一遍加邊地合併上去,然後列舉小的塊的每個點,二分大的塊,然而這還是要遍歷一遍小的塊再遍歷一遍大的塊才能預處理出道鏈結的兩個點的距離,就不滿足啟發式合併的nlogn了,因為要對大的...

poj1741(樹的點分治)

題目連線 poj 1741 看了好長時間才明白了點.網上講解很多但感覺都不夠詳細。大概是太弱了吧 學通了再回來寫詳解。1 include2 include3 include4 include5 define ll long long 6using namespace std 7const int n...