题意:给你一颗树,问你有多少个点对满足他们的距离恰好为k。
题解:
很裸的一个点分治。
1.找到重心。
2.对每一棵子树中的每一个点,都直接询问k-deep的个数,加到答案里,每次处理对一棵子树询问完之后,把这个树的每个节点的深度加到deep的个数里。
3.对个数清0,然后处理每一棵子树的信息。
4.重复1-4的处理,直到没有树了。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define lch(x) tr[x].son[0] 12 #define rch(x) tr[x].son[1] 13 #define max3(a,b,c) max(a,max(b,c)) 14 #define min3(a,b,c) min(a,min(b,c)) 15 typedef pair<int,int> pll; 16 const int inf = 0x3f3f3f3f; 17 const LL INF = 0x3f3f3f3f3f3f3f3f; 18 const LL mod = (int)1e9+7; 19 const int N = 1e5 + 100; 20 vector<int> vc[N]; 21 int n, k, u, v; 22 int sz[N], vis[N]; 23 int mxr, rt; 24 void Getw(int o, int u, int num){ 25 sz[u] = 1; 26 int mx = 0; 27 for(int i = 0; i < vc[u].size(); ++i){ 28 int v = vc[u][i]; 29 if(o == v || vis[v]) continue; 30 Getw(u, v, num); 31 sz[u] += sz[v]; 32 mx = max(sz[v], mx); 33 } 34 if(o) mx = max(mx, num - sz[u]); 35 if(mx < mxr) mxr = mx, rt = u; 36 } 37 int cnt[N]; 38 LL ans = 0; 39 void DFS(int o, int u, int deep){ 40 cnt[deep] += 1; 41 sz[u] = 1; 42 for(int i = 0; i < vc[u].size(); ++i){ 43 int v = vc[u][i]; 44 if(vis[v] || v == o) continue; 45 DFS(u, v, deep+1); 46 sz[u] += sz[v]; 47 } 48 } 49 void cal(int o, int u, int deep){ 50 int m = k - deep; 51 if(m < 0) return ; 52 ans += cnt[m]; 53 for(int i = 0; i < vc[u].size(); ++i){ 54 int v = vc[u][i]; 55 if(vis[v] || v == o) continue; 56 cal(u, v, deep+1); 57 } 58 } 59 void GG(int u, int num){ 60 if(num == 1) return ; 61 mxr = inf; 62 Getw(0, u, num); 63 vis[rt] = 1; 64 for(int i = 0; i < vc[rt].size(); ++i){ 65 int v = vc[rt][i]; 66 if(vis[v]) continue; 67 cal(0, v, 1); 68 DFS(0, v, 1); 69 } 70 int nrt = rt; 71 for(int i = 1; i <= mxr; i++) cnt[i] = 0; 72 for(int i = 0; i < vc[nrt].size(); ++i){ 73 int v = vc[nrt][i]; 74 if(vis[v]) continue; 75 GG(v, sz[v]); 76 } 77 } 78 int main(){ 79 scanf("%d%d", &n, &k); 80 for(int i = 1; i < n; ++i){ 81 scanf("%d%d", &u, &v); 82 vc[v].pb(u); 83 vc[u].pb(v); 84 } 85 cnt[0] = 1; 86 GG(1, n); 87 printf("%I64d ", ans); 88 return 0; 89 }