树上最大带权路径长度和

题目:http://codeforces.com/contest/1092/problem/F

分析:拿第一个样例来说,先维护f,s两个数组,f[x]表示以x为根的子树的所有结点到x的带权路径长度和,s[x]表示以x为根的子树所有结点包括x结点的权值和。假设y是x结点的儿子,那么把以y为根的子树当作一个整体,该整体内部的带权路径长度和(内部)+该整体所有结点权值和(外部)即等于以y为根的子树对x产生的带权路径长度和的贡献。

比如图中x=1,y=5,以y为根的子树的所有结点有6,7,8号,到y(5号)结点的WPL和为1*1+6*1+5*1=12,即f[5]=12,而以y为根的子树所有结点权值和为10+1+6+5=22,即s[5]=22,那么以5号结点为根的子树对1号结点产生的WPL贡献为f[5]+s[5]=34,这样可以求出以1号结点为根的子树的WPL=47,然后关键是要选一个根结点使以该根节点为根的子树的WPL最大。

关键步骤:比如刚刚已经求了以1号结点为根的子树的WPL,然后现子求它的邻接点的,此时要对所扩展的邻接点的f,s实施间接更新,具体看代码

树上最大带权路径长度和_第1张图片

AC code:

#include
using namespace std;
const int maxn=2e5+2;
typedef long long ll;
int val[maxn];
ll _max;
ll f[maxn],s[maxn];
vectoredge[maxn];
void dfs(int u,int fa)
{
    s[u]=val[u];
    f[u]=0;
    for(int i=0;i

 

法二:

#include
using namespace std;
const int maxn=2e5+2;
typedef long long ll;
ll val[maxn];
ll sum;
ll _max;
vectoredge[maxn];
void dfs(int u,int fa,int dp)///求出以1号结点为根结点的WPL和
{
    for(int i=0;i

 

你可能感兴趣的:(动态规划)