CodeForces 161D Distance in Tree 树上点分治

题目传送门

题意:给你一颗树,问你有多少个点对满足他们的距离恰好为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\n", ans);
88     return 0;
89 }
View Code

猜你喜欢

转载自www.cnblogs.com/MingSD/p/9761920.html
今日推荐