題目連接:QAQc++
題目大意:給出一棵n個點的樹,每一個點上有\(C_i\)頭牛,問每一個點k步範圍內各有多少頭牛。git
首先看看數據範圍,\(n\le1e5,k\le20\),那咱們能夠嘗試設\(f[n][k]\)spa
設\(d[i][j]\)表示從i點開始向下k的範圍內有多少頭牛,\(f[i][j]\)表明從i點開始j範圍內有多少頭牛code
\(d[i][j]\)能夠很容易算出來,對於一個點\(u\),\(d[u][j]=C_u+\sum_{v\in son_u}d[v][j-1]\)get
而\(f[i][j]\)也能夠得出,\(f[v][j]=f[fa[v]][j-1]-d[v][j-2]+d[v][j]\)it
最後輸出\(f[i][k]\)就好了io
#include<bits/stdc++.h> using namespace std; const int N=1e5+1; int n,k,cnt,head[N]; int a[N],d[N][21],f[N][21]; struct Edge{int nxt,to;}edge[N<<1]; void ins(int x,int y){ edge[++cnt].nxt=head[x]; edge[cnt].to=y;head[x]=cnt; } void dfs(int x,int fa,int u){ d[x][u]+=a[x]; for(int i=head[x];i;i=edge[i].nxt){ int y=edge[i].to; if(y==fa) continue; d[x][u]+=d[y][u-1]; dfs(y,x,u); } } void calc(int x,int fa,int u){ int w=u-2>=0?d[x][u-2]:0; f[x][u]=f[fa][u-1]-w+d[x][u]; for(int i=head[x];i;i=edge[i].nxt) if(edge[i].to!=fa) calc(edge[i].to,x,u); } void work(int u){ for(int i=head[1];i;i=edge[i].nxt) calc(edge[i].to,1,u); } int read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch)){x=x*10+ch-48;ch=getchar();} return x*f; } int main(){ n=read(),k=read(); for(int i=1;i<n;i++){ int x=read(),y=read(); ins(x,y),ins(y,x); } for(int i=1;i<=n;i++) a[i]=read(),d[i][0]=a[i]; if(!k){ for(int i=1;i<=n;i++) printf("%d\n",a[i]); return 0; } for(int i=1;i<=k;i++) dfs(1,0,i),f[1][i]=d[1][i]; for(int i=1;i<=n;i++) f[i][0]=a[i]; for(int i=1;i<=k;i++) work(i); for(int i=1;i<=n;i++) printf("%d\n",f[i][k]); return 0; }