OpenJudge1043 树上游戏(换根dp+细节处理)

树上游戏

给定一棵 nnn 个节点的树,点从 111nnn 编号,点有点权,边有边权, Alice\text{Alice}AliceBob\text{Bob}Bob 两人在做游戏。

棋子以某一个点 sss 为起点,玩家移动该棋子,有以下两条规则:

  1. 移动时不能经过已经走过的边
  2. 能移动则必须移动,不能在可移动时停留在原地

Alice\text{Alice}Alice 开始,轮流移动棋子,最终的得分为经过的点权之和减去经过的边权之和。

Alice\text{Alice}Alice 想要最大化得分, Bob\text{Bob}Bob 想要最小化得分,假设两人都采取最优策略,那么最终得分是多少呢?

请你对于每个点为起点都输出一个答案。
1≤n≤105,∣vi∣,∣wi∣≤1091\le n\le 10^5,\vert v_i\vert,\ \vert w_i\vert \le 10^91n105,vi, wi109


不难发现当起点确定时可以通过如下树形dp确定结果:

状态表示:fu,0/1f_{u,0/1}fu,0/1uuu为起点向子树中移动,当前该Alice/Bob\text{Alice}/\text{Bob}Alice/Bob最终的值
状态转移:
下面valu\text{val}_uvalu表示uuu的点权,wiw_iwi表示u→vu\to vuv的边权

  • Alice\text{Alice}Alice需要让结果尽可能大:fu,0=max⁡v∈sonu(fv,1+valu−wi)f_{u,0}=\max_{v\in \text{son}_u}(f_{v,1}+\text{val}_u-w_i)fu,0=maxvsonu(fv,1+valuwi)
  • Bob\text{Bob}Bob需要让结果尽可能小:fu,1=min⁡v∈sonu(fv,0+valu−wi)f_{u,1}=\min_{v\in \text{son}_u}(f_{v,0}+\text{val}_u-w_i)fu,1=minvsonu(fv,0+valuwi)

注意:在叶子节点进行初始化

由于存在换根操作,不难发现只要记录fu,0f_{u,0}fu,0的最大次大值以及fu,1f_{u,1}fu,1的最小次小值即可从父节点更新子节点实现换根操作。


注意这种情况:
当前根是uuu,准备换根到vvv,我们需要让uuu的信息去更新vvv的信息,如果vvv在树中是叶子节点,需要特殊地uuu的信息直接赋给vvv而不是更新,因为vvv是叶子节点,在以uuu为根时走到vvv就会停止,而在以vvv为根时,并不会停止并且一定会向uuu移动!!!

还有在第一遍dfs时不能以入度为1的点为根进行dfs,因为这个点在其他点为根的时是叶子节点,某些信息会错误更新比如下面数据

5
2147483647 2147483647 2147483647 2147483647 -2147483647 
1 2 2147483647
2 3 2147483647
3 4 2147483647
4 5 2147483647

总的来说需要注意叶子节点的信息的更新

#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
using ll=long long;
constexpr int N=100010;
constexpr ll INF=0x3f3f3f3f3f3f3f3f;
int h[N],e[2*N],ne[2*N],w[2*N],idx;
void add(int a,int b,int c){e[idx]=b,w[idx]=c,ne[idx]=h[a],h[a]=idx++;}
int val[N],n;
ll f[N][2],g[N][2],ans[N];// f[u][0/1]表示u子树 该A/B移动
int fr[N][2];
int d[N];
bool leaf[N];
void update(int u,int k,int v,ll x)// 更新 最大次大/最小次小
{if(k==0){if(x>f[u][k]) {g[u][k]=f[u][k];f[u][k]=x;fr[u][k]=v;}else if(x>g[u][k]) g[u][k]=x;}else{if(x<f[u][k]){g[u][k]=f[u][k];f[u][k]=x;fr[u][k]=v;}else if(x<g[u][k]) g[u][k]=x;}
}
void dfs1(int u,int fa)
{leaf[u]=1;for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa) continue;leaf[u]=0;dfs1(v,u);for(int k=0;k<=1;k++)update(u,k,v,f[v][k^1]+val[u]-w[i]);}if(leaf[u]) f[u][0]=f[u][1]=val[u];//叶子节点初值
}
void dfs2(int u,int fa)
{ans[u]=f[u][0];for(int i=h[u];i!=-1;i=ne[i]){int v=e[i];if(v==fa) continue;for(int k=0;k<=1;k++){if(leaf[v])//叶子节点特殊处理{if(fr[u][k]==v) f[v][k^1]=g[u][k]+val[v]-w[i];else f[v][k^1]=f[u][k]+val[v]-w[i];}else//换根{if(fr[u][k]==v) update(v,k^1,u,g[u][k]+val[v]-w[i]);elseupdate(v,k^1,u,f[u][k]+val[v]-w[i]);}}dfs2(v,u);}
}
int main()
{ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);cin>>n;memset(h,-1,sizeof h);for(int i=1;i<=n;i++) cin>>val[i];for(int i=1;i<=n;i++) f[i][0]=g[i][0]=-INF,f[i][1]=g[i][1]=INF;for(int i=1;i<n;i++){int a,b,c;cin>>a>>b>>c;add(a,b,c),add(b,a,c);d[a]++,d[b]++;}int rt=1;while(d[rt]==1) rt++;//找一个度数不为1的为根dfs1(rt,0);dfs2(rt,0);for(int i=1;i<=n;i++) cout<<ans[i]<<'\n';
}

这题我一共写了4次
第一次:比赛口胡
第二次:赛后写代码没过懒得调了
第三次:2021/01/04刚放寒假重新写,没注意叶子的细节一直没过
第四次:2021/02/25快开学了准备吧收藏夹的题补一补,有看见这个题,造了造特数数据发现了代码问题,注意到叶子细节成功AC(经历2.5h)

终于把这题干掉了!!!
要加油哦~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/319008.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

牛客题霸 转圈打印矩阵 C++题解/答案

牛客题霸 转圈打印矩阵 C题解/答案 题目描述 给定一个整型矩阵matrix&#xff0c;请按照顺时针转圈的方式打印它。 示例1 输入 复制 [[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]] 返回值 复制 [1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10] 题解&#xff1a; 题意很明确…

【招聘(上海)】东方财富证券招聘.net开发

东方财富证券&#xff1a;东方财富网(深创&#xff1a;300059)旗牌照齐全证券公司&#xff0c;极具互联网基因的券商。.Net服务端开发工程师/.Net前端开发工程师[职位介绍]服务端&#xff1a;开户、交易及资讯系统的后端接口服务(Asp.Net WebApi)开发&#xff1b;服务端&#x…

2020牛客NOIP赛前集训营-提高组(第三场)C-牛半仙的妹子Tree【虚树,最短路】

正题 题目链接:https://ac.nowcoder.com/acm/contest/7609/C 题目大意 给出nnn个点的一棵树&#xff0c;mmm个时刻各有一个操作 标记一个点&#xff0c;每个点被标记后的每一个时刻会标记掉周围的点。删去所有点的标记询问一个点是否有标记 解题思路 考虑没有二操作怎么搞&…

codeforces773 D. Perishable Roads(思维+最短路)

D. Perishable Roads 题意简述&#xff1a; 一个 nnn 个点的完全图 以 iii 为根节点时 询问 能构造的树的 ∑d(x)\sum d(x)∑d(x) 最小是多少。 d(x)d(x)d(x)&#xff1a; xxx 到根节点边权值最小值 MOONPIE题解 首先有一个显而易见的错误贪心&#xff1a; 不妨假设以root\t…

牛客题霸 两数之和C++题解/答案

牛客题霸 两数之和 C题解/答案 题目描述 给出一个整数数组&#xff0c;请在数组中找出两个加起来等于目标值的数&#xff0c; 你给出的函数twoSum 需要返回这两个数字的下标&#xff08;index1&#xff0c;index2&#xff09;&#xff0c;需要满足 index1 小于index2.。注意&…

P3244-[HNOI2015]落忆枫音【dp】

正题 题目链接:https://www.luogu.com.cn/problem/P3244 题目大意 给出一个DAG\text{DAG}DAG&#xff0c;保证111可以到达所有点。然后再加入一条边&#xff08;之后不一定是DAG\text{DAG}DAG&#xff09;。 求有多少棵以111为根的外向生成树。 1≤n≤105,1≤m≤21051\leq n…

EF Core 实现多租户

SAAS 和多租户SaaS(软件及服务)区别于其他应用程序的主要特征就是能够使客户在使用应用程序时按照使用量付费。他们不需要为软件购买许可&#xff0c;也不需要安装、托管和管理它。这方面的操作全部由提供 SaaS 软件的组织负责。多租户是实现 SaaS 的关键因素, 它可以让多个企业…

P3246 [HNOI2016]序列(莫队+单调栈+ST表)

[HNOI2016]序列 Tea神题解 Kelin神题解 对于莫队算法最主要的是如何快速算出[l,r]→[l,r1][l,r]\to[l,r1][l,r]→[l,r1]对答案的贡献的变化。 当询问区间发生上述变化时[l,r]→[l,r1][l,r]\to [l,r1][l,r]→[l,r1]不难发现子区间增加这些&#xff1a;[l,r1],[l1,r1],…,[r,r1…

P6672-[清华集训2016]你的生命已如风中残烛【结论】

正题 题目链接:https://www.luogu.com.cn/problem/P6672 题目大意 长度为mmm的序列aaa&#xff0c;有nnn个数字不是000&#xff0c;其他m−nm-nm−n个是000。要求重排后有多少方案满足 ∀x,∑i1xai≥i\forall x,\sum_{i1}^xa_i\geq i∀x,i1∑x​ai​≥i 其中m∑i1naim\sum_{i…

牛客题霸 反转链表 C++题解/答案

题目描述 输入一个链表&#xff0c;反转链表后&#xff0c;输出新链表的表头。 示例1 输入 复制 {1,2,3} 返回值 复制 {3,2,1} 题解&#xff1a; 如果用偷懒的方法&#xff0c;可以用vector来存链表内容&#xff0c;然后来个翻转&#xff08;vector自带&#xff09;即可 但是…

【.NET Core项目实战-统一认证平台】第五章 网关篇-自定义缓存Redis

上篇文章【.NET Core项目实战-统一认证平台】第四章 网关篇-数据库存储配置&#xff08;2&#xff09;我们介绍了2种网关配置信息更新的方法和扩展Mysql存储&#xff0c;本篇我们将介绍如何使用Redis来实现网关的所有缓存功能&#xff0c;用到的文档及源码将会在GitHub上开源&a…

P5934-[清华集训2012]最小生成树【最小割】

正题 题目链接:https://www.luogu.com.cn/problem/P5934 题目大意 给出nnn个点mmm条边的一张图&#xff0c;再加入一条边(u,v,L)(u,v,L)(u,v,L)求至少删掉多少条边可以使得这条边即在最小生成树上又在最大生成树上。 1≤n≤2104,1≤m≤21051\leq n\leq 2\times 10^4,1\leq m\…

广州.net俱乐部12月份ABP框架活动场地征集、志愿者征集、合作讲师\副讲师征集...

大家好&#xff0c;我在<被低估的.net(上) - 微软MonkeyFest 2018广州分享会活动回顾>一文中提到&#xff0c;我将在12月份搞一场ABP框架活动&#xff0c;现向大家征集活动场地、志愿者、合作讲师\副讲师。活动课程标题是&#xff1a;如何用ABP框架快速完成项目这是内容大…

4152. [AMPPZ2014]The Captain(稠密图最短路)

4152. [AMPPZ2014]The Captain 显然稠密图的边数时n2n^2n2量级&#xff0c;我们不可能把所有边建立出来&#xff0c;这时候通常寻求一些性质详细见【论题选编】稠密图最短路 针对本题我们可以先这样考虑&#xff0c;假设每个点有且只有一维信息&#xff0c;那么任意两点之间的…

牛客题霸 二分查找 C++题解/答案

牛客题霸 二分查找 C题解/答案 题目描述 请实现有重复数字的有序数组的二分查找。 输出在数组中第一个大于等于查找值的位置&#xff0c;如果数组中不存在这样的数&#xff0c;则输出数组长度加一。 示例1 输入 复制 5,4,[1,2,4,4,5] 返回值 复制 3 题解&#xff1a; 二分模…

CF1446F-Line Distance【计算几何,树状数组,二分】

正题 题目链接:https://www.luogu.com.cn/problem/CF1446F 题目大意 给出nnn个点&#xff0c;求所有点对构成的直线中与原点距离第kkk小的距离 2≤n≤105,1≤k≤n(n−1)22\leq n\leq 10^5,1\leq k\leq \frac{n(n-1)}{2}2≤n≤105,1≤k≤2n(n−1)​ 解题思路 二分还是挺显然的…

牛客题霸 判断链表中是否有环 C++题解/答案

牛客题霸 判断链表中是否有环 C题解/答案 题目描述 判断给定的链表中是否有环 扩展&#xff1a; 你能给出空间复杂度的解法么&#xff1f; 题解&#xff1a; 在这介绍一个简便的方法&#xff1a;快慢指针 就是&#xff1a;一个指针走两步&#xff0c;一个指针走一步 快慢指…

为什么是容器,Docker和Kubernetes?

如果你是一名IT行业的从业者&#xff0c;还没有听说过以上3个词的任何一个&#xff0c;抱歉&#xff0c;你可以改行了&#xff1b;如果你是一名技术人员&#xff0c;无论你是程序员&#xff0c;测试人员&#xff0c;运维工程师还是时髦的DevOps工程师&#xff0c;你还没有运行过…

P2685 [TJOI2012]桥(最短路+线段树)

P2685 [TJOI2012]桥 xcxcli题解 下面思路仿照上述题解&#xff0c;代码基本照抄上述题解 u⇝vu\leadsto vu⇝v表示uuu到vvv的最短路 u→vu\to vu→v表示uuu和vvv直接相连的边 d1ud1_ud1u​表示1⇝u1\leadsto u1⇝u的最短路 dnudn_udnu​表示n⇝vn\leadsto vn⇝v的最短路 题意化…

牛客题霸 [斐波那契数列] C++题解/答

斐波那契数列 题目描述 大家都知道斐波那契数列&#xff0c;现在要求输入一个整数n&#xff0c;请你输出斐波那契数列的第n项&#xff08;从0开始&#xff0c;第0项为0&#xff0c;第1项是1&#xff09;。 n<39 题解&#xff1a; 斐波那契数列。。递推的基础题目 众所周…