/*
题意:n个点组成的树,点和边都有权值,当第一次访问某个点的时候获得利益为点的权值
每次经过一条边,丢失利益为边的权值。问从第i个点出发,获得的利益最大是多少。
输入:
测试样例组数T
n
n个数每个点的权值
n-1条无向边 a b c a和b是点的标号,c是边的权值。
思路:
注意题目只强调是从某个点出发,并不一定要回到该点。
考虑树形DP。
先随便定义一个树根。然后对于某个点,我们需要维护它子树方向的两个值
1.从该点出发,最终要回到该点的利益的最大值
2.从该点出发,最终不必回到该点的利益的最大值,以及最后一次从该点出发的是哪个儿子节点。
3.从该点出发,最终不必回到该点的利益的第二大值,以及最后一次从该点出发的是哪个儿子节点。
先求出回到该点的利益的最大值,然后枚举它的儿子节点,作为最后出去的节点,即该节点不返回。
第二和第三个值把枚举所有儿子作为最后一次出发的情况然后排序记录下前两个就可以了。
以上是第一次DFS所做的工作。
然后对于每个点维护三个值,进行第二次DFS。
1.从该点出发所有方向(子树方向和父亲方向)回到该点的利益的最大值。
2.从该点出发所有方向,不必回到该点的利益的最大值,并保存最后一个出发的儿子节点的标号。
3.从该点出发所有方向,不必回到该点的利益的第二大值,并保存最后一个出发的儿子节点的标号。
第1个值的维护只需要将子树方向和减掉本身所在子树所影响的父亲方向的值加起来即可。
对于第二个和第三个值,我们可以将子树方向上最大的两个值加上父亲方向回来所带来的利益,与
父亲方向作为最后一次出发的点不回来的利益这三个值中求取两个最大的即可。
之所以要维护第二大的值,是因为当父亲节点最终的答案(即可以不回来)的最后一次访问的点恰
好是我们要求取的它的儿子节点的时候,我们可以用次大的值来确定当该儿子节点的父亲方向作为
最后一次访问的方向的时候的利益。
最后所有的ans[i][1]就是答案。
总结“
1.树形DP维护的时候经常需要维护次大值甚至第三大值,这是由于父亲方向的最优问题是否关系到
儿子节点所决定的。
*/ #include<bits/stdc++.h>
#define N 100050
using namespace std;
struct edge{
int id;
edge *next;
long long w;
};
struct st{
st(int a,long long b){
id=a;
ans=b;
}
long long ans;
int id;
};
bool cmp(st a,st b){
return a.ans>b.ans;
}
int ednum;
edge edges[N*];
edge *adj[N];
long long v[N],son[N][],ans[N][];
int fa[N],id[N][];
inline void addedge(int a,int b,long long w){
edge *tmp=&edges[ednum++];
tmp->w=w;
tmp->id=b;
tmp->next=adj[a];
adj[a]=tmp;
}
void dfs(int pos){
son[pos][]+=v[pos];
for(edge *it=adj[pos];it;it=it->next){
if(fa[pos]!=it->id){
fa[it->id]=pos;
dfs(it->id);
if(son[it->id][]-*it->w>){
son[pos][]+=son[it->id][]-*it->w;
}
}
}
son[pos][]=son[pos][];
vector<st>mv;
mv.push_back(st(,son[pos][]));
mv.push_back(st(,son[pos][]));
for(edge *it=adj[pos];it;it=it->next){
if(fa[it->id]==pos){
if(son[it->id][]-it->w>){
long long tn=son[pos][]+son[it->id][]-it->w;
if(son[it->id][]-*it->w>)tn-=son[it->id][]-*it->w;
if(tn>son[pos][]){
mv.push_back(st(it->id,tn));
}
}
}
}
sort(mv.begin(),mv.end(),cmp);
son[pos][]=mv[].ans;
id[pos][]=mv[].id;
son[pos][]=mv[].ans;
id[pos][]=mv[].id;
}
void dfs2(int pos){
if(pos==){
for(int i=;i<;i++){
ans[pos][i]=son[pos][i];
}
}
for(edge *it=adj[pos];it;it=it->next){
if(fa[it->id]==pos){
long long tans=ans[pos][]-*it->w;
if(son[it->id][]-*it->w>){
tans-=son[it->id][];
tans+=*it->w;
}
tans=max(0LL,tans);
ans[it->id][]=son[it->id][]+tans;
vector<st>mv;
mv.push_back(st(,ans[it->id][]));
mv.push_back(st(,ans[it->id][]));
for(int i=;i<;i++){
mv.push_back(st(id[it->id][i],son[it->id][i]+tans));
}
if(id[pos][]!=it->id){
long long tm=ans[pos][];
tm+=son[it->id][];
if(son[it->id][]-*it->w>){
tm-=son[it->id][]-*it->w;
}
mv.push_back(st(id[pos][],tm-it->w));
}
else{
long long tm=ans[pos][];
tm+=son[it->id][];
if(son[it->id][]-*it->w>){
tm-=son[it->id][]-*it->w;
}
mv.push_back(st(id[pos][],tm-it->w));
}
sort(mv.begin(),mv.end(),cmp);
ans[it->id][]=mv[].ans;
id[it->id][]=mv[].id;
ans[it->id][]=mv[].ans;
id[it->id][]=mv[].id;
dfs2(it->id);
}
}
}
int main()
{
int t;
scanf("%d",&t);
int cas=;
while(t--){
cas++;
printf("Case #%d:\n",cas);
int n;
scanf("%d",&n);
for(int i=;i<=n;i++){
for(int j=;j<;j++){
son[i][j]=id[i][j]=ans[i][j]=;
}
adj[i]=NULL;
fa[i]=;
}
ednum=;
for(int i=;i<=n;i++)scanf("%lld",v+i);
for(int i=;i<n;i++){
int a,b;long long w;
scanf("%d%d%lld",&a,&b,&w);
addedge(a,b,w);
addedge(b,a,w);
}
dfs();
dfs2();
for(int i=;i<=n;i++){
printf("%lld\n",ans[i][]);
}
}
}

HDU 5834 [树形dp]的更多相关文章

  1. hdu 4123 树形DP+RMQ

    http://acm.hdu.edu.cn/showproblem.php? pid=4123 Problem Description Bob wants to hold a race to enco ...

  2. HDU 1520 树形dp裸题

    1.HDU 1520  Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> ...

  3. HDU 1561 树形DP入门

    The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  4. HDU 2196树形DP(2个方向)

    HDU 2196 [题目链接]HDU 2196 [题目类型]树形DP(2个方向) &题意: 题意是求树中每个点到所有叶子节点的距离的最大值是多少. &题解: 2次dfs,先把子树的最大 ...

  5. HDU 1520 树形DP入门

    HDU 1520 [题目链接]HDU 1520 [题目类型]树形DP &题意: 某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知 ...

  6. codevs 1380/HDU 1520 树形dp

    1380 没有上司的舞会 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 回到问题 题目描述 Description Ural大学有N个职员 ...

  7. hdu 4267 树形DP

    思路:先dfs一下,找出1,n间的路径长度和价值,回溯时将该路径长度和价值清零.那么对剩下的图就可以直接树形dp求解了. #include<iostream> #include<al ...

  8. hdu 4607 (树形DP)

    当时比赛的时候我们找出来只要求出树的最长的边的节点数ans,如果要访问点的个数n小于ans距离直接就是n-1 如果大于的话就是(n-ans)*2+ans-1,当时求树的直径难倒我们了,都不会树形dp ...

  9. hdu 1520 (树形DP)

    dp[i][0]表示i不参加 dp[i][1]表示i参加 简单的树形dp #include<stdio.h> #include<string.h> #define N 6100 ...

随机推荐

  1. Python报错UnicodeDecodeError: 'ascii' codec can't decode byte 0xe0 in position 0: ordinal not in range(128)

    解决办法: 在报错的页面添加代码: import sys reload(sys) sys.setdefaultencoding('utf8')

  2. Linux-LVS+keepalived-Testing

    LVS:Linux Virtual Server+++++++++++++Info+++++++++++VIP:172.18.20.222LVS-Master IP:172.18.20.206LVS- ...

  3. MongoDB权限管理之用户名和密码的操作

    MongoDB默认是不需要输入用户名和密码,客户就可以登录的.但是出于安全性的考虑,我们还是要为其设置用户名和密码.本文主要介绍的是MongoDB权限管理之用户名和密码的操作,希望能对您有所帮助. 本 ...

  4. html颜色字体字符代码

    HTML字体代码表 宋体 SimSun   宋体:SimSuncss中中文字体(font-family)的英文名称 黑体 SimHei   Mac OS的一些: 微软雅黑 Microsoft YaHe ...

  5. MyEclipse配置Resin启动报错问题

    错误信息如下: com.caucho.config.ConfigException: -server 'default' is an unknown server in the configurati ...

  6. Winform用匿名方法新建线程的方法

    作用:1.将耗时的操作放在单独的线程,加快UI的响应速度.Thread t = new Thread(delegate() { parse.ParseDay(StockCode, FileName); ...

  7. 图像特征提取之(一)HOG特征

    1.HOG特征: 方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测的特征描述子.它通过计算和统计图像局部区域的 ...

  8. 线性判别分析(Linear Discriminant Analysis)转载

    1. 问题 之前我们讨论的PCA.ICA也好,对样本数据来言,可以是没有类别标签y的.回想我们做回归时,如果特征太多,那么会产生不相关特征引入.过度拟合等问题.我们可以使用PCA来降维,但PCA没有将 ...

  9. MySQL存储引擎MyISAM与InnoDB的优劣

    使用MySQL当然会接触到MySQL的存储引擎,在新建数据库和新建数据表的时候都会看到. MySQL默认的存储引擎是MyISAM,其他常用的就是InnoDB了. 至于到底用哪种存储引擎比较好?这个问题 ...

  10. 如何把python最小化安装在客户机上面

    因为想尝试在我们的桌面软件中加入python支持,所以想简化python的库,到时候直接放到客户机上面,并且放到我们的目录下,尽量免去不必要的东西,也不要影响机子,不过当写好的程序放到测试机子上后,老 ...