CF771C Bear and Tree Jumps
题目大意:
给定一棵有
解法:
一道换根
首先看到树上统计问题,考虑树形
此时我们发现,这个状态定义十分的不可做,无法计算贡献和转移。
观察到
这个时候就很好转移了,直接有:
但是这统计的只是子树中的贡献,没有统计子树外的,那么自然而然的就想到了换根
设
显然的可以推出公式了。
code:
#include<bits/stdc++.h> #define int long long using namespace std; const int N=2e5+10; int n,k,g[N][6],f[N][6],siz[N],ans,val[6]; struct edge{ int v,next; }edges[N*2]; int head[N],idx; void add_edge(int u,int v){ idx++; edges[idx].v=v; edges[idx].next=head[u]; head[u]=idx; return; } void dfs1(int u,int fa){ siz[u]=1; for(int i=head[u];i;i=edges[i].next){ int v=edges[i].v; if(v==fa)continue; dfs1(v,u); g[u][0]+=siz[v]+g[v][k-1]; for(int j=1;j<k;j++)g[u][j]+=g[v][j-1]; siz[u]+=siz[v]; } return; } void dfs2(int u,int fa){ if(u==1){for(int i=0;i<=k;i++)f[u][i]=g[u][i];} else{ val[0]=f[fa][0]-g[u][k-1]-siz[u]; for(int i=1;i<k;i++)val[i]=f[fa][i]-g[u][i-1]; f[u][0]=g[u][0]+val[k-1]+n-siz[u]; for(int i=1;i<k;i++)f[u][i]=g[u][i]+val[i-1]; } for(int i=head[u];i;i=edges[i].next){ int v=edges[i].v; if(v!=fa)dfs2(v,u); } return; } signed main(){ std::ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); cin>>n>>k; for(int i=1;i<n;i++){ int x,y; cin>>x>>y; add_edge(x,y);add_edge(y,x); } dfs1(1,0);dfs2(1,0); for(int i=1;i<=n;i++)ans+=f[i][0]; cout<<ans/2; return 0; }
本文作者:Little_corn
本文链接:https://www.cnblogs.com/little-corn/p/18157511
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步