給出一棵帶邊權的樹,問有多少對點的距離<=len
這是一道點分治的經典題目,可以給點分治的初學者練手。
點分治,顧名思義就是把每個點分開了處理答案。
假設,目前做到了以x為根的子樹。
先求出子樹中每個點到根的距離di
s ,對於兩個點
i 和
j,如果di
si+d
isj<=
k ,那麼(i
,j) 就是乙個合法的點對。
而點對的路徑就會有兩種:經過x點的和不經過x點的。
顯然,不經過x點的一定會再x的兒子的子樹中被計算過。所以,我們要減去不經過x點的。
那怎麼把不經過x點的減去呢?
用以x為根的子樹的di
s 值(why?如果用以x的兒子為根的子樹的di
s ,就會有些可以到達x的兒子的卻不能到達x的點對,被多減掉),來計算以x的兒子為根的子樹中的點對數量,用減去它們就可以了。
記住要找重心
#include
#include
#include
#include
#include
#include
#include
const
long
long maxlongint=2147483647;
using
namespace
std;
long
long dis[12000],next[22000],last[20020],to[20200],n,m,tot,v[20200],d[5000],sum=0,size[20020],mx[20020],f,root,ans;
bool bz[20020];
long
long bj(long
long x,long
long y,long
long z)
void findroot(long
long x,long
long fa)
}mx[x]=max(mx[x],f-size[x]);
if (mx[x]return;
}void q(long
long l,long
long r)
}if(iif(llong
long dg1(long
long x,long
long fa)
}}long
long getsum()
}return y;
}long
long dg(long
long x,long
long fa)
}}int main()
mx[0]=maxlongint;
f=n;
findroot(1,0);
dg(root,0);
printf("%lld\n",ans);
}
點分治模板 (樹中點對距離)
點分治就是在一棵樹中,將每個點分治 基本概念 點分治 將一棵無根樹變成有根樹,再分別處理每棵有根子樹。重心 在一棵樹中,這個點的最大子樹是所有點中最小的。也可以說是刪除該點時,樹內剩下的子樹最大節點數最小。size i 表示以i為根的子樹節點數量。如何求重心?求出size,什麼是定義,就怎麼求。一般...
點分治入門 樹中點對距離詳(?)解
其中樹最多有10000個點,len maxlongint 這是一道模板題目。對於乙個點x,我們考慮如何求解經過x點的路徑方案數,設為f x 考慮直接從x出發做一遍dfs,算出所有未到過的點到x點的距離,然後排序。設兩個指標,如果length l length r len,那麼length l len...
jzoj1166 樹中點對距離 點分治
求一棵樹上有多少條路徑長度 le n leq len len 首先普通點分治。掃瞄的時候將每個點儲存為乙個二元組 di s,gr a dis,gra dis,g ra 分別表示離 分治到的 根的距離,屬於根的那顆子樹。然後按照dis disdi s排序,兩個指標l,r l,rl,r用cn icn i...