题目大意:给你一棵树,每个节点有一个权值,Alice和Bob进行博弈,起点由Alice确定,确定后交替选择下一个点,Alice目标是最终值尽可能大,Bob目标是尽可能小

题解:很明显是树形DP,那么考虑如何dp

设F[i][0/1]表示第i个点先手选/后手选的答案

那么不难想到

F[i][0]=max(F[j][1])+v[i]

F[i][1]=min(F[j][0])+v[i]

一次以1为根进行dfs可以求出选择1为根时的答案,此时考虑换根

换根时将换根前的所有状态保存下来,dfs下去之后求出其子树答案后将状态复原

换根时有两种情况,1、原根的答案是新根推过来的。2、原根的答案不是从新根推过来的

对于第二种情况很简单,我们只需要把原根当做新根的子树然后进行转移即可

考虑第一种情况,将原根变为儿子之后,其F值由除新根之外的所有儿子转移而来

于是很容易想到在原有保存最大值(最小值)的基础上再保存次大值(次小值),这样就可以O(1)更新原根的答案了

更新完后就和第二种情况一样了

代码:

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#define ll long long
#define INF 1e18
using namespace std;
int T,n;
ll v[100001],f[100001][2];
ll mx[100001][2],mn[100001][2];
ll ans;
int mxbh[100001],mnbh[100001];
struct node
{int x,y;
}tr[100001*2];
int hd[100001],nxt[100001*2],rn;
void build(int x,int y){tr[++rn]=(node){x,y};nxt[rn]=hd[x];hd[x]=rn;}
void init()
{rn=0;memset(f,0,sizeof(f));memset(hd,0,sizeof(hd));memset(nxt,0,sizeof(nxt));
}
void dfs(int now,int last)
{int t1=hd[now],t2;mx[now][0]=mx[now][1]=-INF;mn[now][0]=mn[now][1]=INF;mxbh[now]=0;mnbh[now]=0;while(t1){t2=tr[t1].y;if(t2!=last){dfs(t2,now);if(f[t2][1]>=mx[now][0]){mx[now][1]=mx[now][0];mx[now][0]=f[t2][1];mxbh[now]=t2;}else if(f[t2][1]>mx[now][1])mx[now][1]=f[t2][1];if(f[t2][0]<=mn[now][0]){mn[now][1]=mn[now][0];mn[now][0]=f[t2][0];mnbh[now]=t2;}else if(f[t2][0]<mn[now][1])mn[now][1]=f[t2][0];}t1=nxt[t1];}if(mx[now][0]==-INF)mx[now][0]=0;if(mn[now][0]==INF)mn[now][0]=0;//printf("%d:%lld %lld %lld\n",now,mx[now][0],mn[now][0],v[now]);f[now][0]=mx[now][0]+v[now];f[now][1]=mn[now][0]+v[now];//printf("%d %lld %lld %lld\n",now,f[now][1],max1,v[now]);
}
void dfs2(int now,int last)
{ans=max(ans,f[now][1]);//printf("  %d\n",now);//for(int i=1;i<=n;i++)printf("%lld %lld:%d %d\n",f[i][0],f[i][1],mxbh[i],mnbh[i]);//printf(" %lld %lld|%lld %lld\n",mx[now][0],mx[now][1],mn[now][0],mn[now][1]);//printf("\n");int t1=hd[now],t2;ll fi0,fi1,fj0,fj1,tv,mxj0,mxj1,mnj0,mnj1;int mxbhi,mxbhj,mnbhi,mnbhj;while(t1){t2=tr[t1].y;if(t2!=last){fi0=f[now][0];fi1=f[now][1];fj0=f[t2][0];fj1=f[t2][1];mxbhi=mxbh[now];mnbhi=mnbh[now];mxbhj=mxbh[t2];mnbhj=mnbh[t2];if(mxbh[now]==t2){tv=v[now];if(mx[now][1]!=-INF)tv+=mx[now][1];f[now][0]=tv;}if(mnbh[now]==t2){tv=v[now];if(mn[now][1]!=INF)tv+=mn[now][1];f[now][1]=tv;}mxj0=mx[t2][0];mxj1=mx[t2][1];mnj0=mn[t2][0];mnj1=mn[t2][1];if(mxbhj==0)mx[t2][0]=-INF;if(mnbhj==0)mn[t2][0]=INF;if(f[now][1]>=mx[t2][0]){mx[t2][1]=mx[t2][0];mx[t2][0]=f[now][1];mxbh[t2]=now;}else if(f[now][1]>mx[t2][1])mx[t2][1]=f[now][1];if(f[now][0]<=mn[t2][0]){mn[t2][1]=mn[t2][0];mn[t2][0]=f[now][0];mnbh[t2]=now;}else if(f[now][0]<mn[t2][1])mn[t2][1]=f[now][0];f[t2][0]=mx[t2][0]+v[t2];f[t2][1]=mn[t2][0]+v[t2];dfs2(t2,now);f[now][0]=fi0;f[now][1]=fi1;f[t2][0]=fj0;f[t2][1]=fj1;mx[t2][0]=mxj0;mx[t2][1]=mxj1;mn[t2][0]=mnj0;mn[t2][1]=mnj1;mxbh[now]=mxbhi;mnbh[now]=mnbhi;mxbh[t2]=mxbhj;mnbh[t2]=mnbhj;}t1=nxt[t1];}
}
int main()
{scanf("%d",&T);int a,b;while(T--){init();scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%lld",&v[i]);for(int i=1;i<=n;i++){scanf("%d",&a);v[i]-=a;}for(int i=1;i<n;i++){scanf("%d%d",&a,&b);build(a,b);build(b,a);}memset(f,0,sizeof(f));dfs(1,0);ans=-INF;//for(int i=1;i<=n;i++)printf("%lld %lld/%lld %lld:%d %d %lld %lld\n",mx[i][0],mx[i][1],mn[i][0],mn[i][1],mxbh[i],mnbh[i],f[i][0],f[i][1]);dfs2(1,0);//ans=-INF;//for(int i=1;i<=n;i++)ans=max(ans,f[i][1]);//for(int i=1;i<=n;i++)printf("%lld %lld:%d %d\n",f[i][0],f[i][1],mxbh[i],mnbh[i]);printf("%lld\n",ans);}return 0;
}

心得:典型的树形DP的题目,换根时的操作还需要更多练习熟练

转载于:https://www.cnblogs.com/worcher/p/11353849.html

【HDU6662】Acesrc and Travel【树形DP】相关推荐

  1. 【HDU - 6662】Acesrc and Travel(树形dp,博弈dp)

    题干: Acesrc is a famous tourist at Nanjing University second to none. During this summer holiday, he, ...

  2. 树形dp ---- 2018年杭电多校第二场 H travel

    题目大意: 就是给你一个带点权的树,找到3条独立互不相交的路径使得权值和最大 解题思路: 很经典的树形dp 我们设dp[root][j][k]dp[root][j][k]dp[root][j][k]表 ...

  3. 【CodeForces - 1084D】The Fair Nut and the Best Path (树形dp)

    题干: The Fair Nut is going to travel to the Tree Country, in which there are nn cities. Most of the l ...

  4. CodeForces 1084D The Fair Nut and the Best Path(树形dp)

    题目描述 The Fair Nut is going to travel to the Tree Country, in which there are n cities. Most of the l ...

  5. BNUOJ 52305 Around the World 树形dp

    题目链接: https://www.bnuoj.com/v3/problem_show.php?pid=52305 Around the World Time Limit: 20000msMemory ...

  6. [树形dp] Jzoj P5233 概率博弈

    Description 小A和小B在玩游戏.这个游戏是这样的: 有一棵n个点的以1为根的有根树,叶子有权值.假设有m个叶子,那么树上每个叶子的权值序列就是一个1->m 的排列. 一开始在1号点有 ...

  7. fwt优化+树形DP HDU 5909

    1 //fwt优化+树形DP HDU 5909 2 //见官方题解 3 // BestCoder Round #88 http://bestcoder.hdu.edu.cn/ 4 5 #include ...

  8. BZOJ 1040 ZJOI2008 骑士 树形DP

    题目大意:给定一个基环树林,每一个点上有权值,要求选择一个权值和最大的点集,要求点集中的随意两个点之间不能直接相连 最大点独立集--考虑到n<=100W,网络流铁定跑不了,于是我们考虑树形DP ...

  9. POJ 3342 树形DP+Hash

    这是很久很久以前做的一道题,可惜当时WA了一页以后放弃了. 今天我又重新捡了起来.(哈哈1A了) 题意: 没有上司的舞会+判重 思路: hash一下+树形DP 题目中给的人名hash到数字,再进行运算 ...

最新文章

  1. Kafka单机Windows环境搭建
  2. vb listview 修改
  3. 世界最成功的僵尸网络使用Fast Flux技术躲避检测
  4. 计算碳原子系综的能级C
  5. 转贴:[转]所有 OLE api 和接口的目的
  6. Linux sync命令的作用分析
  7. ref与out一看就懂
  8. 批量执行命令(SSH)
  9. 点计算机没有本地磁盘,快速解决WinPE系统下没有本地磁盘的方法
  10. 机器学习第六回-无监督学习—— K-均值算法
  11. 为企业搭建Gitlab软件版本管理服务器
  12. java 双倍长密钥3des_用Java实现的单倍长密钥DES、双倍长密钥3DES和Mac计算
  13. 请实现一个函数,用来判断一颗二叉树是不是对称的。注意,如果一个二叉树同此二叉树的镜像是同样的,定义其为对称的。
  14. Java8 - Stream API快速入门
  15. 【Gym - 101234G】Dreamoon and NightMarket 【子集中第K大元素】
  16. linux启动tongweb命令,TongWeb安装配置--Linux
  17. spring cloud入门组件教程
  18. 佳能2900打印机与win10不兼容_windows10系统64位如何安装佳能LBP2900驱动?
  19. 在react脚手架中使用Tailwind CSS (入门)
  20. 9.8.1 1.打印head标签的内容。2.打印body标签的内容。3.打印id为Hi的标签对象

热门文章

  1. 阿里云服务器 Windows连接不成功 提示“你的凭证不工作” 解决方法
  2. 关于32bit与4Gib的问题
  3. C#面试题汇总(未完成)
  4. 数据结构与算法分析——引论
  5. [转贴]无刷新的2个DropDownList联动
  6. 二叉树遍历的递归、非递归方法(前序、中序、后序,层序)——Java实现
  7. 使 IDEA 的 termina l可以使用 Linux 下的终端命令
  8. python 搭建web应用程序_用Python构建数据科学Web应用程序
  9. 给容器中注册组件 || @Scope -- @Lazy -- @Conditional({Condition}) -- @Import--使用Spring提供的 FactoryBean
  10. 异常 —— throws