树中的距离题解
Description
洛谷传送门
Solution
似乎各种做法都可以过,这里提供一篇\(dsu\ on\ tree\)(树上启发式合并)的题解。
不会的同学可以看我的博客浅谈树上的数据服务单元
题目要求我们求出长度为\(k\)的路径有多少条。
那么我们可以开一个桶\(cnt_x\),表示深度为\(x\)的点有多少个,统计答案时\(ans=CNT _ { k-dep[x]2 * dep[topx]} \)类似于树上差分的思想)。
然后修改就比较板子了,加入一个点的话就\(cnt_{dep[x]} \),删除的话就\(cnt_{dep[x]} - \)
其他的就没有什么了。
具体看代码吧。
Code
#包含输入输出流
#包含cstdio
#包含算法
#定义陆线(landlines的缩写)长
使用命名空间标准;
const int N=6e 410
int n,k;
ll ans
结构节点{
int v,nxt
}边[^ 1];
int head[N],tot
子,子,子,子;
int CNT[N];
内联void add(int x,int y){ 0
edge[ tot]=(node){y,head[x]};
head[x]=tot;
}
内嵌空dfs(int x,int p){ 0
dep[x]=dep[p] 1,siz[x]=1,fa[x]=p;
for(int I=head[x];我;i=edge[i].NXT){ 0
int y=edge[i].五;
if(y==p)继续;
dfs(y,x);
siz[x]=siz[y];
if(!son[x] || siz[y] siz[son[x]])
son[x]=y;
}
}
内联void update(int x,int topfa,int type){//type=0:加入1: 删除2: 统计答案
if(!type)CNT[dep[x]];
else if(type==1)CNT[dep[x]]-;
else if(k-dep[x](dep[topfa]1)=0)ans=(ll)CNT[k-dep[x](dep[topfa]1)];//这里前面要判一下,不然会兹就
for(int I=head[x];我;i=edge[i].NXT){ 0
int y=edge[i].五;
if(y!=fa[x])
更新(y,topfa,类型);
}
}
内联void solve(int x,int type){//type=1表示是重儿子,类型=0表示是轻儿子
for(int I=head[x];我;i=edge[i].NXT){ 0
int y=edge[i].五;
if(y!=son[x] y!=fa[x])求解(y,0);
}
如果(子[x])求解(子[x],1);//加入重儿子
ans=(ll)CNT[dep[x]k];//从当前点向下k个单位
CNT[dep[x]];//加入根节点
for(int I=head[x];我;i=edge[i].NXT){ 0
int y=edge[i].五;
if(y==fa[x] || y==son[x])继续;
更新(y,x,2);//统计答案
更新(y,x,0);//加入轻儿子
}
if(!类型)更新(x,x,1);//删除轻儿子
}
int main(){ 0
scanf('%d%d ',n,k);
for(int I=1;I n;I){ 0
int u,v;
scanf('%d%d ',u,v);
加(u,v),加(v,u);
}
dfs(1,0);
求解(1,0);
printf('%lld\n ',ans);
返回0;
}
End
本文来自博客园,作者:xixike,转载请注明原文链接:https://www .cn博客。com/xixixike/p/15473244。超文本标记语言
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/52953.html