题目:
输入点数为N一棵树,求树上长度恰好为K的路径个数
分析:
题目的数据范围不是很紧,点分治也可以过,树形dp也可以过。这里采用点分治做法。
我们只需要单开一个类似于桶的数组,跑点分治套路,统计即可,每次处理一棵子树,先在桶上跑统计,处理完一棵子树再更新桶。这样可以保证每一段路径都直接跨过根节点内。
记得开long long。
代码:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int N=100005,M=505; 5 struct node{int y,nxt;}e[N*2]; 6 int d[N],rt,vis[N],siz[N],c=1,q[N]; 7 int h[N],n,m,k,mx[N],sm;ll t[M],ans=0; 8 void add(int x,int y){ 9 e[++c]=(node){y,h[x]};h[x]=c; 10 } void getrt(int x,int fa){ 11 siz[x]=1;mx[x]=0; 12 for(int i=h[x],y;i;i=e[i].nxt) 13 if((y=e[i].y)!=fa&&!vis[y]) 14 getrt(y,x),siz[x]+=siz[y], 15 mx[x]=max(mx[x],siz[y]); 16 mx[x]=max(mx[x],sm-siz[x]); 17 if(mx[x]<mx[rt]) rt=x;return ; 18 } void dfs(int x,int fa){ 19 q[++q[0]]=d[x]; 20 for(int i=h[x],y;i;i=e[i].nxt) 21 if((y=e[i].y)!=fa&&!vis[y]) 22 d[y]=d[x]+1,dfs(y,x);return ; 23 } void calc(int x){ 24 for(int i=h[x],y;i;i=e[i].nxt) 25 if(!vis[y=e[i].y]){ 26 q[0]=0;d[y]=1;dfs(y,x); 27 for(int j=q[0];j;j--) 28 if(q[j]<=k) ans+=t[k-q[j]]; 29 for(int j=q[0];j;j--) 30 if(q[j]<=k) t[q[j]]++; 31 } memset(t,0,sizeof(t)); 32 } void solve(int x){ 33 vis[x]=1;t[0]=1;calc(x); 34 for(int i=h[x],y;i;i=e[i].nxt) 35 if(!vis[y=e[i].y]){ 36 sm=siz[y];mx[rt=0]=N; 37 getrt(y,0);solve(rt); 38 } return ; 39 } int main(){ 40 scanf("%d%d",&n,&k); 41 for(int i=1,x,y;i<n;i++) 42 scanf("%d%d",&x,&y),add(x,y),add(y,x); 43 mx[rt]=sm=n;getrt(1,0);solve(rt); 44 printf("%lld\n",ans);return 0; 45 }