• 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
    ", ans);
    88     return 0;
    89 }
    View Code
  • 相关阅读:
    编程练习1-输入姓,返回名
    常见clock tree结构
    数字后端概念——followpin
    数字后端文件——SDF文件格式实例
    数字后端基础——各种缩写定义
    低功耗设计——internal power理解
    AXI-4 总结-introduction
    vivado自带仿真器总结
    毕业论文格式调整
    重装电脑任务清单
  • 原文地址:https://www.cnblogs.com/MingSD/p/9761920.html
Copyright © 2020-2023  润新知