标签:sz sum Tree son 最大值 CF1187E Painting 节点 DP
分析
首先,我们贪心的想,当第一个点确定后,我们所求的最大值就是,依次选择子节点
这样,我们可以用树形DP求出以1
为根的树,所能得到的最大权值。
递推公式为
\[f[i] = sz[i] + \sum_{j = son_1}^{son_m}f[j] \]则,我们可以轻松得到
\[f[1] = n + \sum_{j = son_1}^{son_m}f[j] \]但是我们需要求出以每个点为根节点能得到的最大值的最大值
当然不难想到,用换根DP啦。
推换根DP的公式
子节点son
分为两部分,前边为原本son
下边的,后边的是,将父节点变为子节点后的贡献。
我们开始对式子进行拼接变形。
\[g[son] = n + \sum_{j = son_1}^{son_s}f[j] + sz[son] - sz[son] + g[f] - sz[son] - f[son] \]其中分别加sz[son]
原因是为了是把那一个Σ处理一下。
式子最后变为
\[g[son] = n + f[son] + sz[son] + g[f] - 2*sz[son] - f[son] \]\[g[son] = n + sz[son] + g[f] - 2*sz[son] \]好嘞,直接看代码。
Ac_code
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
int h[N],ne[N<<1],e[N<<1],idx;
LL f[N],g[N],sz[N];
int n;
void add(int a,int b)
{
e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
void dfs1(int u,int fa)
{
sz[u] = 1;
for(int i=h[u];~i;i=ne[i])
{
int j = e[i];
if(j==fa) continue;
dfs1(j,u);
sz[u] += sz[j];
f[u] += f[j];
}
f[u] += sz[u];
}
void dfs2(int u,int fa)
{
for(int i=h[u];~i;i=ne[i])
{
int j = e[i];
if(j==fa) continue;
g[j] = g[u] + n - 2 * sz[j];
dfs2(j,u);
}
}
int main()
{
scanf("%d",&n);
memset(h,-1,sizeof h);
for(int i=0;i<n-1;i++)
{
int u,v;scanf("%d%d",&u,&v);
add(u,v),add(v,u);
}
dfs1(1,-1);
g[1] = f[1];
dfs2(1,-1);
LL ans = 0;
for(int i=1;i<=n;i++) ans = max(ans,g[i]);
printf("%lld\n",ans);
return 0;
}
标签:sz,sum,Tree,son,最大值,CF1187E,Painting,节点,DP 来源: https://www.cnblogs.com/aitejiu/p/16267727.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。