【BZOJ4297】[PA2015]Rozstaw szyn

Description

给定一棵有n个点,m个叶子节点的树,其中m个叶子节点分别为1到m号点,每个叶子节点有一个权值r[i]。你需要给剩下n-m个点各指定一个权值,使得树上相邻两个点的权值差的绝对值之和最小。

Input

第一行包含两个正整数n,m(2<=n<=500000,1<=m<=n),分别表示点数和叶子数。
接下来n-1行,每行两个正整数u,v(1<=u,v<=n),表示u与v之间有一条边。
接下来m行,每行一个正整数,依次为r[1],r[2],...,r[m](1<=r[i]<=500000),表示每个叶子的权值。

Output

输出一个整数,即树上相邻两个点的权值差的绝对值之和的最小值。

Sample Input

6 4
1 5
2 5
3 6
4 6
5 6
5
10
20
40

Sample Output

35

题解:思路同BZOJ1304,咱们先来证几个结论:

1.我们从下往上逐层贪心,每次选择一个点的取值范围时,只保证它与它的儿子之间差的绝对值之和最小,而不考虑它的父亲。这样为什么是对的呢?假如x的最优值为v,我们为了使它的父亲更优,将x的取值改为v+d,那么x与x父亲之间的差会减小d,但 x的所有值<=v的儿子 与x之间的差都增加了d。具体地,如果x有a个儿子,那么增加量至少是d。显然是没有一开始优的。

2.以哪个非叶子节点为根进行DP,最后得到的答案都是一样的。假如当前根为x,x的儿子是y。那么如果x的最优取值区间被y包含,相当于x和y之间的差可以为0,那么如果把y当成根,则y的取值区间显然也会被x包含(不要问为什么显然~)。否则我们不考虑x-y这条边,x的取值范围是[l,r],那么在考虑y的贡献后x的取值范围只可能是[...,l]或[r,...],即其他点对x的影响可视为不变,那么只需要最后加上x-y的贡献即可。把y当根也是同理,所以将那个点当成根答案都是一样的。

所以具体做法:随便找一个点当根进行DP,然后用每个点的儿子的最优取值区间来得到当前点的最优取值区间。具体地,我们将x的所有儿子的最优取值区间的左右端点放到一起排序,然后取中间的那段即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn=500010;
typedef long long ll;
int n,m,cnt;
ll ans;
int to[maxn<<1],next[maxn<<1],head[maxn],l[maxn],r[maxn],p[maxn<<1];
inline void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
void dfs(int x,int fa)
{
if(x<=m) return ;
int i,tot=0;
for(i=head[x];i!=-1;i=next[i]) if(to[i]!=fa) dfs(to[i],x);
for(i=head[x];i!=-1;i=next[i]) if(to[i]!=fa) p[++tot]=l[to[i]],p[++tot]=r[to[i]];
sort(p+1,p+tot+1);
l[x]=p[tot>>1],r[x]=p[(tot>>1)+1];
for(i=head[x];i!=-1;i=next[i]) if(to[i]!=fa&&(r[to[i]]<l[x]||l[to[i]]>l[x]))
ans+=min(abs(l[to[i]]-l[x]),abs(r[to[i]]-l[x]));
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
int main()
{
//freopen("bz4297.in","r",stdin);
n=rd(),m=rd();
int i,j,a,b;
memset(head,-1,sizeof(head));
for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
for(i=1;i<=m;i++) l[i]=r[i]=rd();
if(n==m)
{
for(i=1;i<=n;i++) for(j=head[i];j!=-1;j=next[j]) ans+=abs(l[to[j]]-l[i]);
printf("%lld",ans>>1);
return 0;
}
dfs(n,0);
printf("%lld",ans);
return 0;
}

【BZOJ4297】[PA2015]Rozstaw szyn 树形DP的更多相关文章

  1. BZOJ4297 : [PA2015]Rozstaw szyn

    每个点的最优取值范围是一个区间,将叶子一层层剥去,得到一棵有根树,父亲的取值范围由儿子推得,时间复杂度$O(n\log n)$. #include<cstdio> #include< ...

  2. [PA2015]Rozstaw szyn

    [PA2015]Rozstaw szyn 题目大意: 一棵\(n(n\le5\times10^5)\)个点的树,其中有\(m\)个结点是叶子结点.叶子结点权值已知,你可以自己决定其余结点的权值,定义整 ...

  3. bzoj 4297: [PA2015]Rozstaw szyn【瞎搞】

    从叶子往上先拓扑一下,建立虚拟root,从root开始dfs.注意到每个点的最优取值一定是一个区间(中位数区间),从儿子区间推出父亲区间即可 #include<iostream> #inc ...

  4. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  5. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  6. 【BZOJ-4726】Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  7. 树形DP+DFS序+树状数组 HDOJ 5293 Tree chain problem(树链问题)

    题目链接 题意: 有n个点的一棵树.其中树上有m条已知的链,每条链有一个权值.从中选出任意个不相交的链使得链的权值和最大. 思路: 树形DP.设dp[i]表示i的子树下的最优权值和,sum[i]表示不 ...

  8. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

  9. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

随机推荐

  1. C#删除xml指定节点

  2. AutoFac文档8(转载)

    目录 开始 Registering components 控制范围和生命周期 用模块结构化Autofac xml配置 与.net集成 深入理解Autofac 指导 关于 词汇表 泛型 给定一个开放的泛 ...

  3. mac appium 启动genymotion

    mac eclipse  appium 启动genymotion 模拟器,设置红框中的三项内容就可以.2个红色箭头不需要设置. 如果launch_avd 设置,就会提示:Emulator xxx no ...

  4. C++一次指针问题和解决(char指针乱码)

    问题始末 struct NameGroup { char* Name1; char* Name2; }; NameGroup A() { NameGroup result; //From other ...

  5. Atitit.mysql oracle with as模式临时表模式 CTE 语句的使用,减少子查询的结构性 mssql sql server..

    Atitit.mysql  oracle with as模式临时表模式 CTE 语句的使用,减少子查询的结构性 mssql sql server.. 1. with ... as (...) 在mys ...

  6. atitit.故障排除------有时会错误com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset by peer: soc

    atitit.故障排除------有时会错误com.microsoft.sqlserver.jdbc.SQLServerException: Connection reset by peer: soc ...

  7. CGROUP相关知识

    安装 CentOS 6 yum install libcgroup CentOS 7 yum install libcgroup-tools 使用 默认情况下有几个控制器可以进行限制,分别是 cpus ...

  8. python学习笔记(4)--聊天记录处理

    说明: 1.把冒号和前面的名字去掉 2.男的台词放一个txt文件,女的台词放一个txt文件 3.遇到======就重新生成一个文件 record.txt: 婷婷:迪迪早啊! 迪迪:早啊! 婷婷:111 ...

  9. VMware12激活码,win10激活码

    VMware Workstation 12序列号: 5A02H-AU243-TZJ49-GTC7K-3C61N win10激活码:这里在网上搜集到很多激活码,可能有的不能用.   WRUF7-AFI0 ...

  10. C语言 · 最大乘积

      算法提高 最大乘积   时间限制:1.0s   内存限制:512.0MB      问题描述 对于n个数,从中取出m个数,如何取使得这m个数的乘积最大呢? 输入格式 第一行一个数表示数据组数 每组 ...