树的中心和重心&树上背包
树的中心和重心
求树的中心:
法1:F[i]为以i为起点的最长链长度
枚举深度最小的点,全部枚举
void dfs(int fa,int x){ for(int i = head[x];i;i = nxt[i]){ if(to[i]==fa) continue; dfs(x,to[i]); ans = max(ans,f[x]+f[to[i]]+1); //是否形成更长链 f[x] = max(f[x],f[to[i]]+1); //尝试合并 } return; }
法2:两次dfs,
第一次:以任意点i为起点,寻找离i最远点j
第二次:以j为起点,寻找最远点k
答案:j-k
树上背包
有体积为v价值为w的背包构成树,选了一个节点就要选父亲,问不超过体积V价值最大的算法
解:每个子树就是一个泛化物品。
f[u][i]表示以u为根体积为i的最大价值
void dfs(int fa,int x){ for(int i = w[x];i <= m;i++) f[x][i] = v[x]; for(int i = head[x];i;i = nxt[i]){ if(to[i] == fa) continue; dfs(x,to[i]); for(int j = m;j;j--){ //枚举体积 for(int k = 0;k <= j-w[x];k++){ f[x][j] = max(f[x][j],f[x][j-k]+f[to[i]][k]); } } } }