题目链接

大意

给出一颗树,每个点上有一个权值\(A[i]\),有两个绝顶聪明的人甲和乙。

甲乙两人一起在树上轮流走,不能走之前经过的点。(甲乙时刻在一起)

甲先手,并可以确定起点。甲想要走过的点权之和最大,乙想要权值和最小。

求最终权值和。

思路

首先有个很明显的想法就是树形Dp:

设\(F0[u]\)表示以\(u\)为根的子树内,甲先手,以\(u\)为起点的权值和。

设\(F1[u]\)表示以\(u\)为根的子树内,乙先手,以\(u\)为起点的权值和。

那么转移式就为:

\(F0[u]=Min(F1[v])+A[u]\)

\(F1[u]=Max(F0[v])+A[u]\)

其中\(v\)为\(u\)的一个儿子。

这样我们可以处理出每个点只在其子树范围走内的答案。


考虑从某个点出发,向上走形成的答案。



我们设\(TP[V]\)表示不走\(V\)的子树,甲先手,以\(V\)为起点的权值和。

那么\(TP[V]\)的更新就会有两种情况,一种是先走\(U\),然后再走\(U\)的某个儿子。



对于这种情况,甲肯定会选\(U\)的儿子中\(F0\)最大的值,即\(F1[U]\)。

但又由于\(V\)可能本身就是最大的,所以应该记录下\(F1\)的最大值与次大值进行转移。

对于另一种,就是先走\(U\),再走\(Fa\)的情况。



对于这种情况,在走到\(Fa\)时,\(B\)肯定会选择较小的那一边走。

所以就是\(Fa\)所有儿子中最小的\(F1\),即\(F0[Fa]\)与\(Fa\)向上走的情况\(TP[Fa]\)取较小值就行了。

但同理,\(U\)可能是最小的,所以记录下\(F0\)的最小值与次小值进行转移。

对于以上两种\(TP\)情况的选择由于是\(A\)选,所以取较大值。

注:在转移\(TP\)时,时刻注意为一条链的情况。

最后枚举以哪一个点为起点,取\(F0[U][0]\)与\(TP[U]\)的较小值就行了。

注意叶子节点与根的取值。

代码

细节超多,易错点主要集中在初值的赋值以及根上。

  1. #include<cstdio>
  2. #include<vector>
  3. #include<algorithm>
  4. using namespace std;
  5. const int MAXN=600005;
  6. const long long INF=1e17;
  7. int K,N,A[MAXN];
  8. int son0[MAXN],son1[MAXN];
  9. long long Ans;
  10. long long F0[MAXN][2],F1[MAXN][2];//0:A|||||||1:B
  11. long long TP[MAXN];
  12. vector<int>P[MAXN];
  13. void DFS(int u,int fa){
  14. int Ok=0;
  15. int size=P[u].size();
  16. for(int i=0;i<size;i++){
  17. int v=P[u][i];
  18. if(v==fa)continue;
  19. DFS(v,u);Ok=1;
  20. if(F1[v][0]+A[u]<F0[u][0])F0[u][1]=F0[u][0],F0[u][0]=min(F0[u][0],F1[v][0]+A[u]),son0[u]=v;
  21. else F0[u][1]=min(F0[u][1],F1[v][0]+A[u]);
  22. if(F0[v][0]+A[u]>F1[u][0])F1[u][1]=F1[u][0],F1[u][0]=max(F1[u][0],F0[v][0]+A[u]),son1[u]=v;
  23. else F1[u][1]=max(F1[u][1],F0[v][0]+A[u]);
  24. }
  25. if(!Ok)F0[u][0]=F0[u][1]=F1[u][0]=F1[u][1]=A[u];
  26. }
  27. void DFS2(int u,int fa){
  28. int size=P[u].size();
  29. for(int i=0;i<size;i++){
  30. int v=P[u][i];
  31. if(v==fa)continue;
  32. long long val1=INF,val2=INF;
  33. if(P[u].size()!=2){
  34. if(son1[u]==v)val1=F1[u][1];
  35. else val1=F1[u][0];
  36. }else val1=u==1?A[u]:-INF;
  37. if(P[fa].size()!=2){
  38. if(son0[fa]==u)val2=F0[fa][1];
  39. else val2=F0[fa][0];
  40. }val2=min(val2,TP[fa]);
  41. TP[v]=A[v]+max(val1,val2+A[u]);
  42. DFS2(v,u);
  43. }
  44. }
  45. int main(){
  46. //freopen("data.txt","r",stdin);
  47. //freopen("mine.txt","w",stdout);
  48. scanf("%d",&K);
  49. while(K--){
  50. scanf("%d",&N);
  51. for(int i=0;i<=N;i++){
  52. F0[i][0]=F0[i][1]=INF;
  53. F1[i][0]=F1[i][1]=-INF;
  54. son0[i]=son1[i]=0;TP[i]=-INF;
  55. P[i].clear();
  56. }
  57. for(int i=1;i<=N;i++)scanf("%d",&A[i]);
  58. for(int i=1,x;i<=N;i++)scanf("%d",&x),A[i]-=x;
  59. if(N==1){
  60. printf("%d\n",A[1]);
  61. continue;
  62. }
  63. for(int i=1,x,y;i<N;i++){
  64. scanf("%d%d",&x,&y);
  65. P[x].push_back(y);
  66. P[y].push_back(x);
  67. }Ans=-INF;P[1].push_back(0);
  68. DFS(1,0);
  69. if(P[1].size()!=2)TP[1]=INF;
  70. else TP[1]=A[1];
  71. DFS2(1,0);
  72. Ans=F0[1][0];
  73. for(int i=2;i<=N;i++){
  74. if(P[i].size()==1)Ans=max(Ans,TP[i]);
  75. else Ans=max(Ans,min(F0[i][0],TP[i]));
  76. }
  77. printf("%lld\n",Ans);
  78. }
  79. }

【HDU6662】Acesrc and Travel(树型Dp)的更多相关文章

  1. 2019杭电多校 hdu6662 Acesrc and Travel (树形dp

    http://acm.hdu.edu.cn/showproblem.php?pid=6662 题意:有两个人在树上博弈,每个点节点有两个分数a[i]和b[i],先手先选择一个点,后手在先手选的点的相邻 ...

  2. 【题解】Luogu p2986 [USACO10MAR]伟大的奶牛聚集Great Cow Gat 树型dp

    题目描述 Bessie is planning the annual Great Cow Gathering for cows all across the country and, of cours ...

  3. POJ3659 Cell Phone Network(树上最小支配集:树型DP)

    题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. ...

  4. POJ 3342 - Party at Hali-Bula 树型DP+最优解唯一性判断

    好久没写树型dp了...以前都是先找到叶子节点.用队列维护来做的...这次学着vector动态数组+DFS回朔的方法..感觉思路更加的清晰... 关于题目的第一问...能邀请到的最多人数..so ea ...

  5. 【XSY1905】【XSY2761】新访问计划 二分 树型DP

    题目描述 给你一棵树,你要从\(1\)号点出发,经过这棵树的每条边至少一次,最后回到\(1\)号点,经过一条边要花费\(w_i\)的时间. 你还可以乘车,从一个点取另一个点,需要花费\(c\)的时间. ...

  6. 洛谷P3354 Riv河流 [IOI2005] 树型dp

    正解:树型dp 解题报告: 传送门! 简要题意:有棵树,每个节点有个权值w,要求选k个节点,最大化∑dis*w,其中如果某个节点到根的路径上选了别的节点,dis指的是到达那个节点的距离 首先这个一看就 ...

  7. 【POJ 3140】 Contestants Division(树型dp)

    id=3140">[POJ 3140] Contestants Division(树型dp) Time Limit: 2000MS   Memory Limit: 65536K Tot ...

  8. Codeforces 581F Zublicanes and Mumocrates(树型DP)

    题目链接  Round 322 Problem F 题意  给定一棵树,保证叶子结点个数为$2$(也就是度数为$1$的结点),现在要把所有的点染色(黑或白) 要求一半叶子结点的颜色为白,一半叶子结点的 ...

  9. ZOJ 3949 (17th 浙大校赛 B题,树型DP)

    题目链接  The 17th Zhejiang University Programming Contest Problem B 题意  给定一棵树,现在要加一条连接$1$(根结点)和$x$的边,求加 ...

随机推荐

  1. MYSQL 自定义序列函数

    代码如下: DROP TABLE SEQNUM; -- 创建序列表 CREATE TABLE SEQNUM( ID BIGINT ); -- 插入初识值 insert INTO SEQNUM valu ...

  2. Python调用aiohttp

    1. aiohttp安装 pip install aiohttp 1.1. 基本请求用法 async with aiohttp.get('https://github.com') as r: awai ...

  3. Keil MDK STM32系列(九) 基于HAL和FatFs的FAT格式SD卡TF卡读写

    Keil MDK STM32系列 Keil MDK STM32系列(一) 基于标准外设库SPL的STM32F103开发 Keil MDK STM32系列(二) 基于标准外设库SPL的STM32F401 ...

  4. Appium+python自动化测试过程中问题

    一.自动删除contactmanager 自动化测试appium提供的sample如下包/activity:com.example.android.contactmanager/.ContactMan ...

  5. unittest测试框架

    unittest单元测试框架不仅可以适用于单元测试,还可以适用WEB自动化测试用例的开发与执行,该测试框架可组织执行测试用例,并且提供了丰富的断言方法,判断测试用例是否通过,最终生成测试结果. 一.u ...

  6. docker安装、下载镜像、容器的基本操作

    文章目录 一.docker安装与基本使用 1.docker的安装.从远程仓库下载镜像 2.配置docker国内源 二.创建容器 1.create i.创建容器 ii.进入容器 iii.启动容器 2.r ...

  7. [STM32F4xx 学习] SPI小结

    一.STM32F4xx系列的SPI特点: 1. 支持全双工的3线SPI模式(即SCK, MISO, MOSI) 2. 支持单工2线传输,同时数据线可以设置成单向或者双向模式 3. 8-bit, 16- ...

  8. manjora20安装搜狗输入法

    先安装好fcitx和yay yay -S fcitx-sogoupinyin sudo pacman -S base-devel 这是因为需要使用外网,需要配置代理. 注意 manjora20输入法一 ...

  9. Cesium源码剖析---视频投影

    Cesium中的视频投影是指将视频作为一种物体材质,实现在物体上播放视频的效果.这个功能在Cesium早期版本中就支持了,在Code Example中有一个示例.今天就来分析一下其内部实现原理. 1. ...

  10. Java on Visual Studio Code的更新 – 2022年1月

    大家好,欢迎来到 Visual Studio Code Java 更新 1 月版!这是我们新年的第一篇博客,我们将回顾 2021 年的亮点,并分享我们 2022 年的产品路线图!除此之外我们还有一些令 ...