思路:这题涉及距离k,k肯定要作为一个状态的。首先选一个根节点,dfs序作为有根树。
我们设d[i][j] : 顶点i向下dfs, j距离内的点权和,可以直接dfs求得,dp[i][0]为边界
递推过程:d[i][j]=c[i]+Σd[child][j-1]
设f[i][j] : 距离顶点i ,j距离内的点权和, f[i][0] f[1][j]作为边界. 可以直接求出来
递推过程是父节点->子节点 , f[child][j]=f[rt][j-1]+d[child][j]-w;
其中,当j>=2 w=d[child][j-2] 否则w=0;
这里为啥要减去d[child][j-2]呢?因为当j>=2,f[rt][j-1]会包括进d[child][j-2]的这些点,相当于重复计数了,所以根据容斥原理得减掉。
最终答案就是f[i][k]
总的来说,这题比较巧妙,首先是预处理d[i][k] 。
然后是想到f[[i][j]中的边界是根节点,从而确立父节点->孩子节点的方向。
最后是对于换根过程中产生的重复计算部分的处理,减去d[child][j-2]
//#pragma comment(linker, "/STACK:102400000,102400000")//手动扩栈
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<stdlib.h>
#include<string.h>
#include<string>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<math.h>
#include<set>
#include<unordered_map>
using namespace std;
#define LL long long
#define ULL unsigned long long
const int INF=0x3f3f3f3f;
const double eps=1e-5;
const int maxn=1e5+7;
//思路:d[i][j]表示点i向下dfs,距离小于等于j的点的个数,包括自己 f[i][j] 离点i j距离以内的点的个数
//f[i][j]=f[father[i]][j-1]+d[i][j]-