[校内测试]宝藏(树形DP)

JZOJsenior5477.【NOIP2017提高组】day2T2宝藏 problemDescription 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋,也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度。 小明决心亲自前往挖掘所有宝藏屋中的宝藏。但是,每个宝藏屋距离地面都很远,也就是说,从地面打通一条到某个宝藏屋的道路是很困难的,而开发宝藏屋之间的道路则相对容易很多。 小明的决心感动了考古挖掘的赞助商,赞助 阅读详情

=== ===

这里写图片描述
这里写图片描述

=== ===

题解

比较好想的树形DP。。但是实现起来很多地方不是一般恶心。。。也许是ATP的方法太愚蠢了?总之好像当时考试的时候ATP最后半个小时想出来了但是没码完只好写了50pts部分分= =醉死了

那就先从50pts的开始说起吧。。可以想到这个数据范围允许我们把每个节点当做根每次都重新进行dfs,那就用一个f[i][0]表示从i号节点出发到它的子树里去转一圈最后还要回来的最大收益,f[i][1]表示从i号节点出发到它的子树里转一圈最后不回来的最大收益。那么分别以每个点u为根dfs的时候最大收益就是f[u][0]和f[u][1]的Max。

但是100pts的话肯定不能每次重新dfs,就要考虑一遍dfs维护出所有需要的信息。因为它要的是一定经过某一个点的最大收益路线,一遍dfs的话只能维护出从这个点出发到它的子树里走一圈的最大收益,于是再维护一个g[i][0]数组代表从i这个点出去到它的子树外面走一圈并且回来的最大收益,g[i][1]表示从这个点出去走一圈并且回来的最大收益。但是注意的情况是递推g数组的时候因为要分成在它父亲外面走一圈和在它兄弟节点里走一圈两种情况,所以搞它的兄弟节点的时候不能包括它本身。这个需要注意。

那么到底如何来维护这两个数组呢?对于f[i][0],反正它每次走出去都要回来,所以就一个子树一个子树地考虑。对于当前子树v,f[v][0]是已知的,那么跑到这个子树里面走一圈再回来的收益就可以算出来。如果这个收益大于0,显然选上v这个子树肯定会让解变得更优。也就是说f[i][0]是贪心维护的,枚举每一棵子树的时候只要它的收益大于0就一定要选。

对于f[i][1],它需要在i的所有子树中选一棵子树,当跑到这棵子树里面的时候它就不再回到点i了。除了这棵子树以外的其它子树还是可以用f[v][0]来贪心选择的。那么在递推f[i][1]的时候每次枚举到一个子树v,显然目前的f[i][1]里面存储的结果对应的那棵不回来的子树在v前面。于是就要分成仍然让v之前的那棵子树不回来和让v不回来两种情况讨论。如果仍然让v之前的那棵子树不回来,v就要回来,于是就用f[v][0]贪心地更新;否则因为v要回来,所以v之前所有的都不能回来,就用当前的f[i][0]加上f[v][1]来更新结果——这就要求每次f[i][0]要在f[i][1]之后更新否则f[i][0]里面存的就不是v之前的子树而有可能包括v了,就造成了重复更新。

g数组要求自顶向下而不是自底向上递推,因为只有知道了父亲的情况才能递推儿子。对于g[i][0],它是跑到外面转一圈再回来的最大收益,于是首先继承g[fa][0]的结果,表示它到它父亲节点的外面转了一圈再回来;然后还有它经过父亲到兄弟节点里面转一圈回来的情况,这个肯定不能枚举现算啊对吧,所以我们考虑利用之前的结果。注意到f[fa][0]就已经包括了i的所有兄弟节点的信息,但是问题就在于有可能也同时包括了i,这是不合法的。所以我们要判断一下i有没有对f[fa][0]产生贡献,如果有的话要减去。因为是贪心选择的所以也很好判断。

最后是g[i][1]。需要分成不回来的那条路在它父亲外面还是在它兄弟节点里面两部分讨论。如果不回来的那条路在父亲外面的话就是用g[fa][1]加上它到兄弟节点里转一圈然后回来的收益,这个和上面g[i][0]计算的时候是一样的。关键就是不回来的那条路再兄弟节点里面的这种情况比较麻烦。不能直接用f[fa][1]啥的来更新,因为在计算f[fa][1]的时候所使用的不回来的那个儿子可能本身就是当前要计算的i。也就是用于递推i的那个东西必须保证它不回来的那个儿子必须在i外面。所以在递推f数组的时候又循环了一遍,一开始递推f[u][1]的时候记录了一下它不回来的儿子是哪一个,然后再强制让这个儿子一定拐回来,递推一个f[u][2]。这样在递推g[i][1]的时候,f[fa][1]和f[fa][2]一定至少有一个它选择的不回来的路径是在i外面的,就用那个来更新。更新的时候仍然记得减去可能存在的f[i][0]的贡献。

madan这题解好TM长啊

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,p[300010],a[600010],nxt[600010],tot;
long long f[300010][3],g[300010][2],val[300010],w[600010],rec[300010];
void add(int x,int y,long long v){
    tot++;a[tot]=y;nxt[tot]=p[x];w[tot]=v;p[x]=tot;
}
void dfs(int u,int fa){
    int tmp=val[u],e;
    f[u][0]=f[u][1]=f[u][2]=val[u];//0:back;1:not back
    for (int i=p[u];i!=0;i=nxt[i])
      if (a[i]!=fa){
          int now,last;
          dfs(a[i],u);
          last=f[u][1]+max((long long)0,f[a[i]][0]-2*w[i]);
          now=f[u][0]+max((long long)0,f[a[i]][1]-w[i]);
          if (now>last){
              f[u][1]=now;rec[u]=a[i];
          }else f[u][1]=last;
          if (f[a[i]][0]>=2*w[i]) f[u][0]+=f[a[i]][0]-2*w[i];
      }
    for (int i=p[u];i!=0;i=nxt[i])
      if (a[i]!=fa&&a[i]!=rec[u]){
          int now,last;
          last=f[u][2]+max((long long)0,f[a[i]][0]-2*w[i]);
          now=tmp+max((long long)0,f[a[i]][1]-w[i]);
          f[u][2]=max(now,last);
          if (f[a[i]][0]>=2*w[i]) tmp+=f[a[i]][0]-2*w[i];
      }else if(a[i]==rec[u]) e=w[i];//记下最大值不回来节点的父边来更新
    f[u][2]=max(f[u][2],f[u][2]+f[rec[u]][0]-2*e);//最后要判断一下
}
void dfs_again(int u,int fa,int edge){
    int son;
    g[u][0]=g[u][1]=0;
    if (rec[fa]==u) son=f[fa][2];
    else son=f[fa][1];//判断选择最大值还是次大值
    son-=max(f[u][0]-2*edge,(long long)0);//减去当前子树的影响
    g[u][1]=max(g[u][1],g[fa][0]+son-edge);//停在兄弟节点里的情况
    if (f[u][0]>2*edge) son=f[u][0]-2*edge;
    else son=0;//计算所有兄弟节点回来的价值和
    son=f[fa][0]-son;//停在父亲外面的情况
    g[u][1]=max(g[u][1],son+g[fa][1]-edge);
    g[u][0]=max(g[u][0],son+g[fa][0]-2*edge);
    for (int i=p[u];i!=0;i=nxt[i])
      if (a[i]!=fa) dfs_again(a[i],u,w[i]);
}
int main()
{
    freopen("treasure.in","r",stdin);
    freopen("treasure.out","w",stdout);
    scanf("%d",&n);
    for (int i=1;i<n;i++){
        int x,y,w;
        scanf("%d%d%d",&x,&y,&w);
        add(x,y,w);add(y,x,w);
    }
    for (int i=1;i<=n;i++) scanf("%d",&val[i]);
    dfs(1,0);dfs_again(1,0,0);
    for (int i=1;i<=n;i++)
      printf("%I64d\n",max(f[i][0]+g[i][1],f[i][1]+g[i][0])); 
    return 0;
}

偏偏在最后出现的补充说明

树形DP中对于“一定经过某一个点的啥啥啥”这种问题来说,这是一种常用的思路啦。

西门子触摸屏教程wincc flexible2008 sp5 Smart V3 V4中文版软件 阅读详情

相关推荐

2023电视专用!安卓电子相册APP避坑指南(附开源代码)

本文针对2023年智能电视用户,提供安卓电子相册APP的避坑指南与实战教程。文章详细解析了电视端相册应用的常见广告与兼容性陷阱,并指导用户如何安全获取、部署纯净的APK应用,通过核心设置实现无广告的个性化图片轮播体验,最终打造专属的家庭回忆墙。

weixin_29012677的博客 495

树形DP

一般来说树形dp在设状态转移方程时都可以用f[i][j]f[i][j]f[i][j]表示i这颗子树怎么怎么样的最优解,实现时一般都是用子树更新父亲(即从下向上更新),那么首先应该考虑的是一个一个子树的更新父亲还是把所有子树都算完了在更新父亲?这就要因题而异了,一般来说有两种情况: 1.需要把所有子树的信息都掌握之后再更新子树的就需要把所有子树都算完了在更新父亲。 2.而像树上背包这样的问题就需要一个一个的更新,每次都用一个子树更新已经更新完的子树+父亲,最后就可以将这一部分的子树更新完了,再继续往上更新,最

cqbz_xsh的博客 358

STM32驱动LED矩阵:IS31FL3731与查理复用技术实践

LED矩阵显示是嵌入式系统中常见的人机交互方式,其核心在于高效的驱动技术。查理复用(Charlieplexing)作为一种创新的矩阵扫描方式,通过引脚复用技术,用N个引脚驱动N²-N个LED,大幅提升了硬件资源利用率。IS31FL3731驱动芯片集成了这一技术,配合STM32F410RB微控制器的强大性能,可实现144个LED的精准控制。这种组合在艺术装置、信息展示等场景中展现出独特优势,既能呈现丰富的视觉效果,又能通过内置PWM调光实现256级亮度控制。通过I2C接口通信,开发者可以轻松实现字符显示、图像

weixin_29193359的博客 279

SICILY1138. 寻宝之旅 树形dp

题目描述 国家探险队长 Jack 意外弄到了一份秦始皇的藏宝图,于是,探险队一行人便踏上寻宝之旅,去寻找传说中的宝藏。 藏宝点分布在森林的各处,每个点有一个值,表示藏宝的价值。它们之间由一些小路相连,小路不会形成环,即两个藏宝点之间有且仅有一条道路。探险队从其中的一点出发,每次他们可以留一个人在此点开采宝藏,也可以不留,然后其余的人可以分成若干队向这一点相邻的点走去。需要注意的是,如果他们

qq_37321744的博客 497

告别手动输入!用Burp插件+ddddocr,5分钟搞定图片验证码自动识别

本文详细介绍了如何利用Burp插件和ddddocr开源库快速构建图片验证码自动识别系统,实现高效、零成本的验证码自动化解决方案。通过环境搭建、性能调优和Burp Suite深度集成,显著提升安全测试效率,特别适用于金融和电商系统的批量测试场景。

weixin_29099217的博客 202

基于Halcon与C#的PCB焊接缺陷智能检测系统开发实战(附完整源码与项目文档)

本文详细介绍了基于Halcon与C#的PCB焊接缺陷智能检测系统开发实战,涵盖机器视觉技术、硬件选型、图像处理算法及C#上位机开发。通过实战案例展示如何实现高效、准确的PCB焊接缺陷检测,提升生产效率与质量,并附完整源码与项目文档。

mango的博客 218

【树形DP】树形DP入门详解+例题剖析

树形DP 树形DP准确的说是一种DP的思想,将DP建立在树状结构的基础上。整体的思路大致就是用树形的结构存储数据。 要学树形DP之前肯定是要先学会树和图的呀,至少先学会链式前向星,不会的话可以看一下我之前写的博客 链接:【图论】图,实现图(三种方式),二分图 详解 树形DP的关键和实现方法是dfsdfsdfs。 先找到树根,从树根开始运用 dfsdfsdfs 递归,跟dfsdfsdfs一样先初始化...

繁凡さん的博客 1万+

SDR实战(五)-AD9361多芯片同步技术详解

本文详细解析了AD9361多芯片同步技术在SDR系统中的实现方法,涵盖硬件连接方案、软件配置流程及同步验证技巧。通过等长时钟走线、低抖动时钟分配和精确的SYNC信号控制,解决MIMO系统中多AD9361芯片的时钟同步难题,提升系统性能与稳定性。

weixin_30952535的博客 761

【树形DP】宝藏

Solution挺有意思的一道树形DP,我理解了3个小时…… 这道题目我们想一想后会发现大致要记录两个值:从i开始走再回到i的最大价值,从i开始不回到i的最大价值。 我们用方法一表示走某颗子树走下去再走回来,方法二表示走下去不回来。 我们用f[i]f[i]表示从i开始往子树走,再走回来的最大价值,(可以走很多棵子树),Max[i]Max[i]表示走每棵子树用方法二和方法一的价值之差,显然方法二

Lhq 613

京东/淘宝商品评论情感分析:基于Python的大规模评论爬取与NLP情感分析实战

在当今电商蓬勃发展的时代,用户评论已成为影响消费者购买决策的关键因素。本文将详细介绍如何使用Python最新技术栈爬取京东和淘宝商品评论,并运用先进的自然语言处理技术对评论进行情感分析,识别用户的好评与差评倾向。通过完整的代码实现和深入的技术解析,帮助读者掌握从数据采集到情感分析的全流程。本文详细介绍了如何使用Python最新技术栈实现京东和淘宝商品评论的爬取与情感分析。通过结合异步爬虫、反爬策略、BERT情感分析等先进技术,我们构建了一个完整的评论分析系统。高效爬取。

2201_76125261的博客 1403

从零实现深度学习框架——理解正则化(一)

本文介绍解决过拟合与欠拟合的方法——正则化,主要介绍L1和L2正则化。

日积月累,天道酬勤 3394

宝藏(树形DP)

宝藏(树形DP)

qq_38601996的博客 449

使用Qt Creator自带的Qt Designer构造UI界面流程总结

在本文中,我们将总结使用Qt Creator自带的Qt Designer构造UI界面的流程。在对话框中,您可以选择一个控件的信号,然后将其连接到另一个控件的槽。例如,您可以将按钮的点击信号连接到一个槽函数,以响应按钮的点击事件。右键单击窗口设计器中的空白区域,选择适当的布局管理器,如水平布局、垂直布局或网格布局。在Qt Designer中,您可以使用各种预定义的UI控件来设计应用程序的界面。现在,您可以在应用程序的源代码中使用生成的UI界面。在您的源文件中,包含相应的头文件,然后创建一个UI界面的实例。

cl6789的博客 1394

【NOIP 模拟题】[T2]宝藏(树形dp)

饮月千尺,寂夜成相思

reverie_mjp的博客 832

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

test 宝藏(树形dp)

题解 :树形dp f[i]表示从i出发只能向下走最终回到i的最大值,f1[i]表示从i出发只能向下走 #include #include #include #include #include #define N 300003 using namespace std; int n,m,f[N],g[N],f1[N],f2[N],mark[N],g1[N]; int point[N],next[N

clover_hxy的博客 434

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

[NOIP2017] 宝藏 【树形DP】【状压DP】

题目分析: 这个做法不是最优的,想找最优解请关闭这篇博客。 首先容易想到用$f[i][S][j]$表示点$i$为根,考虑$S$这些点,$i$的深度为$j$情况的答案。 转移如下: $f[i][S][j] = min(w(i,k)*(j+1)+f[k][S_0][j+1]+f[i][S-S_0][j])$ 其中$S != {i}$且$S_0 \subsetneqq S$且$k \in S_0...

weixin_30569001的博客 171

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

树形dp

题目:http://www.gdfzoj.com/oj/contest/161/problems/9 因为宝藏拿了就没了,所以注意循环顺序 代码: #include #include #include #include using namespace std; struct node { int end,t; }; const int maxSize=100; vector

scutbenson的博客 203

宝藏

题目描述 一棵n个点的树,到达一个点会获得这个点上的宝藏,每个宝藏都有一定的价值。经过每条边需要支付一定的过路费。每个点只有一个宝藏,但过路费每次都要交。求从每个点出发能得到的最大收益。 输入 输入文件为treasure.in。 第一行为一个正整数n。 接下来n-1行,每行三个整数x, y, z,描述一条边的两个端点x, y和过路费z。 最后一行n个数,表示每个点上宝藏的价值ai。 输

wang_sj的博客 665

[NOIp2017 TG Day2 T2] 宝藏

原题链接:https://www.luogu.org/problemnew/show/P3959 宝藏 题目描述 参与考古挖掘的小明得到了一份藏宝图,藏宝图上标出了 n 个深埋在地下的宝藏屋, 也给出了这 n 个宝藏屋之间可供开发的 m 条道路和它们的长度。 小明决心亲自前往挖掘所有宝藏屋中的宝藏。但是,每个宝藏屋距离地面都很远, 也就是说,从地面打通一条到某个宝藏屋的道路是很...

ShadyPi的IT笔记 502

P3959 宝藏

P3959 宝藏 又是毒瘤的noip2017年的原题。 考场上太菜了,prim就得了20分。呜呜呜 \(n\)这么小,不状态都对不起这道题呀 原本,我是想的是,dfs搜索,状压记录状态。 发现,这个东西,一个状态会被重复刷新。不满足无后效性。 然后,考虑按照层数拓展,一层拓展上若干个点。 恩,无后效性解决了。可是这个复杂度看起来是\((2^n\cdot 2^n)\)的呀? 不会爆么? 问题的本质...

weixin_34097242的博客 154

【洛谷3959】宝藏(随机算法乱搞)

点此看题面

CXR的博客 508

洛谷P3959 宝藏(NOIp2017)

状压DP 题目传送门 为什么我会觉得prim是对的!为什么我70分的暴力都不打!果然我好菜 我是不会告诉你我不知道怎么枚子集的 n=12就是状压的范围。据说标算O(4n)​O(4n)​O(4^n)​我不会啊,优化过的O(n3n)​O(n3n)​O(n3^n)​我也不会啊,我只会O(n23n)​O(n23n)​O(n^23^n)​啊不管了能过就行! Orz写模拟退火的 f[i][j][s...

forezxl的博客 321

【搜索】【随机化贪心】【NOI2006】聪明的导游

题目描述: 【问题描述】 小佳最近迷上了导游这个工作,一天到晚想着带游客参观各处的景点。正好M 市在举行 NOI,来参观的人特别的多。不少朋友给小佳介绍了需要导游的人。 M 市有 n 个著名的景点,小佳将这些景点从 1 至 n 编号。有一些景点之间存在双向的路。小佳可以让游客们在任何一个景点集合,然后带着他们参观,最后也可以在任何一个景点结束参观。不过,来参观的游客们都不愿去已经参观过的地方。所

void* ptr = &OI; 1446

LG 3959 宝藏

状压DP 蒟蒻想了个\(O(N^3\ast 3^N)\)的 膜拜SZR博客之后 才知道怎么优化掉一个N 码力同翔 1.5h才过样例 SZR's blog #include <iostream> #include <cassert> using namespace std; const long long LONF=4567891012345678910LL; const...

weixin_30480075的博客 122

面试的一个宝藏仓库

阅读文本大概需要3分钟。最近,GitHub 上有一个项目很火,这个项目主要介绍了阿里、腾讯、百度、美团、今日头条等国内互联网大厂的面试题,还配备有答案和出题人分析等信息。...

天行健,君子以自强不息;地势坤,君子以厚德载物。 228
上一篇: [BZOJ3624][Apio2008]免费道路(并查集)
下一篇: [BZOJ1880][Sdoi2009]Elaxia的路线(最短路+拓扑序)
FromATP
博客等级 码龄10年 75粉丝 163原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值