您的位置:首页 > 其它

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

2017-03-19 23:58 381 查看

题目链接

C. Bear and Tree Jumps

分析



其实题解已经说的很清楚了,我最开始不理解的一点在于如何计算剩余f(L,k),看了题解的代码之后才懂了,用一个数组cnt_sub[v][i] 存储以 v 为根的与根节点距离的剩余为 i 的节点数目.然后对于子树 u中的顶点 a,b 计算他们距离的剩余的时候,应为这两个节点u,v的距离一定是 du+dv−2∗(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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  codeforces