codeforces 711C. Bear and Tree Jumps(树上距离)

来源:互联网 发布:jersey解析 json 编辑:程序博客网 时间:2024/05/14 21:44

题目链接

C. Bear and Tree Jumps

分析

这里写图片描述

其实题解已经说的很清楚了,我最开始不理解的一点在于如何计算剩余f(L,k),看了题解的代码之后才懂了,用一个数组cnt_sub[v][i] 存储以 v 为根的与根节点距离的剩余为 i 的节点数目.然后对于子树 u中的顶点 a,b 计算他们距离的剩余的时候,应为这两个节点u,v的距离一定是 du+dv2(LCA) (由于是对它的直接后继进行计算,所以子树深度就是LCA的深度). 由于MOD的性质他们距离的剩余就可以直接枚举k2种情况,然后减去子树深度来获得距离的剩余,以后的事情你一定懂了,就直接递归下去就行了.
题解搬运工

AC code

#include <bits/stdc++.h>using namespace std;typedef long long LL;const int maxn = 2e5+10;std::vector<int> G[maxn];int tatol_sub[maxn];int cnt_sub[maxn][5];//子树中每个剩余的点的总数LL ans;LL n,k;int sub_mod(int a,int b){  return ((a-b)%k+k)%k;}void dfs(int u,int p,int dep){  cnt_sub[u][dep%k] = tatol_sub[u] = 1;  for(int v: G[u]){    if(v!=p){      dfs(v,u,dep+1);      for(int i=0 ; i<k ; ++i){        for(int j =0 ; j<k ; ++j){          int remain = sub_mod(i+j,dep*2);//当前子树中两个节点的距离          int need = sub_mod(k,remain);          ans+=(LL)need*cnt_sub[u][i]*cnt_sub[v][j];        }      }      for(int i = 0 ; i<k ; ++i)        cnt_sub[u][i]+=cnt_sub[v][i];      tatol_sub[u]+=tatol_sub[v];    }  }  ans+=(n-tatol_sub[u])*tatol_sub[u];}int main(int argc, char const *argv[]) {  cin>>n>>k;  ans = 0;  for(int i=0 ; i<n-1 ; ++i){    int u,v;    cin>>u>>v;    G[u].push_back(v);    G[v].push_back(u);  }  dfs(1,-1,0);  std::cout << ans/k << '\n';  return 0;}
0 0
原创粉丝点击