2. 小x游世界树

(yggdrasi.pas/c/cpp)

【问题描述】

小x得到了一个(不可靠的)小道消息,传说中的神岛阿瓦隆在格陵兰海的某处,据说那里埋藏着亚瑟王的宝藏,这引起了小x的好奇,但当他想前往阿瓦隆时发现那里只有圣诞节时才能到达,然而现在已经春天了,不甘心的他将自己的目的地改成了世界树,他耗费了大量的时间,终于将自己传送到了世界树下。世界树是一棵非常巨大的树,它有着许许多多的枝条以及节点,每个节点上都有一个平台。好不容易来到传说中的世界树下,小x当然要爬上去看看风景。小x每经过一条边都会耗费体力值。然而世界树之主想给他弄(gáo)些(dǐan)麻(shì)烦(qíng),

于是他在每条边上都设了一个魔法阵,当小x踏上那条边时会被传送回根节点,魔法阵只生效一次。这岂不是要累死小x?

幸运的是,每个平台上都有无数个加速器,这些加速器可以让小x在当前节点所连的边上耗费的体力值减少,不同平台的加速器性能不一定相同,但同一个平台的加速器性能绝对相同。

世界树之主给了小x一次“换根”的机会,他可以将世界树的任何一个节点变为根,但所有的边都不能改变。小x想问你,将根换为哪个节点能使小x爬到世界树上的每个节点耗费的体力值和最少。默认编号为1的点为初始根。

【输入】

第一行一个数n,表示有n个节点。

第二行n个数ai,表示每个平台上的加速器的性能。

第三至n+1行,每行三个数bi,ci,di分别表示这条无向边的起点,终点与耗费的能量值

【输出】

第一行一个数,表示要换成的节点,如果有多个点为根时耗费的体力值都最小,则输出编号最小的那个。如果保持为1是最优的,就输出1。

第二行一个数,表示最小耗费的体力值。

【输入输出样例1】

4

2 1 3 3

1 2 3

1 3 4

2 4 6

1

9

【数据范围】

对于20%的数据:n<=100

对于40%的数据:n<=1000

对于60%的数据:n<=8000

对于80%的数据:n<=100000

对于100%的数据:0<n<=700000;ai<=1000;1<=bi,ci<=n;di<=1000。

数据保证一个点的加速器性能绝对小于等于它的所有的边所耗费的能量,保证所有节点都可以到达,保证没有数据与样例相同。

【样例解释】

如果以第一个点为根,则需要耗费0(到1)+1(到2)+2(到3)+6(到4)=9的能量值。

如果以第二个点为根,则需要耗费2(到1)+0(到2)+4(到3)+5(到4)=11的能量值。

如果以第三个点为根,则需要耗费1(到1)+2(到2)+0(到3)+7(到4)=10的能量值。

如果以第四个点为根,则需要耗费5(到1)+3(到2)+7(到3)+0(到4)=15的能量值。

很明显以第一个点为根是最优的。


对每条边来说走的次数就是子树的size

先从1开始处理一下1的答案,每次换根只会影响两个点一条边,

只会把这条边的权值贡献从(e[i].w-w[father])*(size[son])变为(e[i].w-w[son])*(size[1]-size[son])

所以直接用回溯遍历推出来每个点为根的答案

有一个点错了是因为字典序的问题

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=;
int n;
struct node{
int v,w,nxt;
}e[maxn<<];
int head[maxn],cnt;
void add(int u,int v,int w){e[++cnt].v=v;e[cnt].w=w;e[cnt].nxt=head[u];head[u]=cnt;}
int size[maxn],w[maxn];
ll f[maxn];
void pre(int x,int fa){
size[x]=;ll tmp=;
for(int i=head[x];i;i=e[i].nxt){
if(e[i].v==fa)continue;
pre(e[i].v,x);
f[x]+=f[e[i].v]+(e[i].w-w[x])*size[e[i].v];
size[x]+=size[e[i].v];
}
}
ll pos,ans=1e15,cost;
void dfs(int x,int fa){
if(ans>cost)pos=x,ans=cost;
for(int i=head[x];i;i=e[i].nxt){
int y=e[i].v;
if(y==fa)continue;
cost-=(e[i].w-w[x])*size[y],cost+=(e[i].w-w[y])*(size[]-size[y]);
dfs(y,x);
cost+=(e[i].w-w[x])*size[y],cost-=(e[i].w-w[y])*(size[]-size[y]);
}
}
int main(){
freopen("yggdrasil.in","r",stdin);
freopen("yggdrasil.out","w",stdout);
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%d",&w[i]);
for(int i=,u,v,w;i<n;i++){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);add(v,u,w);
}
pre(,);
cost=f[];
dfs(,);
printf("%lld\n%lld\n",pos,ans);
}

[题解](树形dp/换根)小x游世界树的更多相关文章

  1. bzoj 3743 [Coci2015]Kamp——树形dp+换根

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3743 树形dp+换根. “从根出发又回到根” 减去 “mx ” . 注意dfsx里真的要改那 ...

  2. poj3585 Accumulation Degree(树形dp,换根)

    题意: 给你一棵n个顶点的树,有n-1条边,每一条边有一个容量z,表示x点到y点最多能通过z容量的水. 你可以任意选择一个点,然后从这个点倒水,然后水会经过一些边流到叶节点从而流出.问你最多你能倒多少 ...

  3. 树形dp换根,求切断任意边形成的两个子树的直径——hdu6686

    换根dp就是先任取一点为根,预处理出一些信息,然后在第二次dfs过程中进行状态的转移处理 本题难点在于任意割断一条边,求出剩下两棵子树的直径: 设割断的边为(u,v),设down[v]为以v为根的子树 ...

  4. poj3585 Accumulation Degree[树形DP换根]

    思路其实非常简单,借用一下最大流求法即可...默认以1为根时,$f[x]$表示以$x$为根的子树最大流.转移的话分两种情况,一种由叶子转移,一种由正常孩子转移,判断一下即可.换根的时候由頂向下递推转移 ...

  5. JZOJ5776. 【NOIP2008模拟】小x游世界树

    题目:[NOIP2008模拟]小x游世界树: 题目的附加题解给的很清楚,这里只给一个代码: #include<iostream> #include<cstdio> #inclu ...

  6. JZOJ 5776. 【NOIP2008模拟】小x游世界树

    5776. [NOIP2008模拟]小x游世界树 (File IO): input:yggdrasil.in output:yggdrasil.out Time Limits: 1500 ms  Me ...

  7. [jzoj 5776]【NOIP2008模拟】小x游世界树 (树形dp)

    传送门 Description 小x得到了一个(不可靠的)小道消息,传说中的神岛阿瓦隆在格陵兰海的某处,据说那里埋藏着亚瑟王的宝藏,这引起了小x的好奇,但当他想前往阿瓦隆时发现那里只有圣诞节时才能到达 ...

  8. 2019ICPC沈阳网络赛-D-Fish eating fruit(树上DP, 换根, 点分治)

    链接: https://nanti.jisuanke.com/t/41403 题意: State Z is a underwater kingdom of the Atlantic Ocean. Th ...

  9. Acwing-287-积蓄程度(树上DP, 换根)

    链接: https://www.acwing.com/problem/content/289/ 题意: 有一个树形的水系,由 N-1 条河道和 N 个交叉点组成. 我们可以把交叉点看作树中的节点,编号 ...

随机推荐

  1. Machine Learning in Action(1) K-近邻

    机器学习分两大类,有监督学习(supervised learning)和无监督学习(unsupervised learning).有监督学习又可分两类:分类(classification.)和回归(r ...

  2. xml 基础属性

    xml属性 对应的方法 说明 android:alpha setAlpha(float) 设置组件的透明度(0——1) android:background setBackgroundResource ...

  3. linux 中mmap的用法

    函数:void *mmap(void *start,size_t length,int prot,int flags,int fd,off_t offsize); 参数start(dst):指向欲映射 ...

  4. CentOS中文乱码之解决办法

    在学习Linux的过程中,最先碰到的是通过SSH终端连接时发现有乱码出现,使用这篇文章先从这里说起. 在 ssh , telnet 终端中文显示乱码解决办法#vim /etc/sysconfig/i1 ...

  5. 内部类访问外部类方法中的参数-使用final

    public synchronized <T extends MetricsSource> T register(final String name, final String desc, ...

  6. BZOJ4936:match (不错的分治)

    给你一个由小写字母组成的字符串s,要你构造一个字典序最小的(认为左括号的字典序比右括号小)合法的括号 序列与这个字符串匹配,字符串和括号序列匹配定义为:首先长度必须相等,其次对于一对匹配的左括号和右括 ...

  7. BZOJ_2716_[Violet 3]天使玩偶&&BZOJ_2648_SJY摆棋子_KDTree

    BZOJ_2716_[Violet 3]天使玩偶&&BZOJ_2648_SJY摆棋子_KDTree Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋 ...

  8. win10 下安装linux子系统

    一.开发人员选项 打开控制面板->程序与功能->启用或关闭windows功能 勾选    [适用于linux的windows子系统]    选项 打开win10设置 找到更新与安全 启动开 ...

  9. This file requires _WIN32_WINNT to be #defined at least to 0x0403. Value 0x0501 or higher is recommended

    VS2005转换成VS2010时出现的问题: This file requires _WIN32_WINNT to be #defined at least to 0x0403. Value 0x05 ...

  10. excel,word,ppt,pdf,swf 文件互相转换

    转自:  http://www.cnblogs.com/wolf-sun/p/3569960.html 引言 之前项目需要,查找了office文档在线预览的解决方案,顺便记录一下,方便以后查询. 方案 ...