HDU4008 Parent and son [树形DP]
给定一棵树,求出当x为根时y的最小儿子和最小后代各是多少。
一道中等的树形DP,首先以1为根进行DP可以求出每个节点的最小儿子和最小后代。只有当x为y的孩子时才需要讨论,否则直接输出前面DP的结果即可,这里画个图就可以看出来,下面只讨论x为y的孩子的情况。
如果y的最小儿子是x的祖宗节点,那这时该最小儿子已经变成了y的父亲,在选取最小儿子时不能在考虑这个点,应该换选次小儿子,所以每个点的次小儿子也要在DP时预处理出来,另外,这时y的原父亲在新树中已经变成了y的儿子,所以在选取最小儿子时要考虑父节点。至于最小后代,如果y不是根节点,那么最小后代必然是根节点1了,如果y节点是根节点,就先找到最小后代在它那个儿子的子树中,如果最小后代和x在同一棵子树中,那么现在已经成为了跟节点的父亲,换而选取其它子树中的最小后代,否则就直接选取最小根节点。
至于祖宗节点的判断,用进出时间戳就可以了,儿子节点的时间戳必然是被父节点夹在中间的。
#include <stdio.h> #include <string.h> #include <algorithm> #define INF 0x3fffffff #define MAXN 100005struct edge{int v,n; }e[MAXN<<1]; int first[MAXN],es; int mins[MAXN][2],mind[MAXN],mind2,mindv,dfn[MAXN][2],fat[MAXN],ds; void addedge(int u,int v){e[es].v=v,e[es].n=first[u],first[u]=es++; } inline int min(int x,int y){return x<y?x:y;} inline void swap(int &x,int &y){x^=y,y=x^y,x=x^y;} void dp(int u,int f){dfn[u][0]=++ds;for(int i=first[u];i!=-1;i=e[i].n){int v=e[i].v;if(v==f)continue;fat[v]=u;dp(v,u);//跟新最小和次小儿子if(v<mins[u][1])mins[u][1]=v;if(mins[u][1]<mins[u][0])swap(mins[u][0],mins[u][1]);//跟新最小后代int tmp=min(v,mind[v]);if(tmp<mind[u])mind[u]=tmp;}dfn[u][1]=++ds; } //判读u是不是v的father int isfather(int u,int v){return dfn[u][0]<=dfn[v][0]&&dfn[v][1]<=dfn[u][1]; } int cas,n,q,tu,tv; int main(){//freopen("test.in","r",stdin);scanf("%d",&cas);while(cas--){scanf("%d%d",&n,&q);for(int i=1;i<=n;i++)first[i]=-1;es=0;for(int i=0;i<n-1;i++){scanf("%d%d",&tu,&tv);addedge(tu,tv);addedge(tv,tu);}for(int i=1;i<=n;i++)mins[i][0]=mins[i][1]=INF;for(int i=1;i<=n;i++)mind[i]=INF;ds=0,fat[1]=INF;dp(1,-1);//跟新根节点次大的孩子,同时记录最小后代与1的最近节点mind2=INF;for(int i=first[1];i!=-1;i=e[i].n){int v=e[i].v,tmp=min(v,mind[v]);if(tmp!=mind[1]&&tmp<mind2)mind2=tmp;if(tmp==mind[1])mindv=v;}while(q--){scanf("%d%d",&tu,&tv);//如果这个点只连了一条边,说明无孩子if(e[first[tv]].n==-1){printf("no answers!\n");//如果tv是tu的父亲(以1为根)}else if(isfather(tv,tu)){int mis,mid;//如果最小的儿子是tu的祖宗节点,则此时已经成为了tv的父亲节点,换为次小的儿子//同时原来的父亲节点已经变成了孩子,要一起考虑if(isfather(mins[tv][0],tu))mis=min(mins[tv][1],fat[tv]);else mis=min(mins[tv][0],fat[tv]);//如果tv是根节点要特判,选取他最大或者次大的后代,否则最小后代就是1if(tv==1)mid=isfather(mindv,tu)?mind2:mind[1];else mid=1;printf("%d %d\n",mis,mid);//其它情况}else{printf("%d %d\n",mins[tv][0],mind[tv]);}}printf("\n");}return 0; }
转载于:https://www.cnblogs.com/swm8023/archive/2012/08/27/2659248.html
HDU4008 Parent and son [树形DP]相关推荐
- UOJ #131 BZOJ 4199 luogu P2178【NOI2015】品酒大会 (后缀自动机、树形DP)
UOJ #131 BZOJ 4199 luogu P2178[NOI2015]品酒大会 (后缀自动机.树形DP) 水是水,但是写出了不少问题,因此写一发博客. https://www.luogu.or ...
- [树形dp] Jzoj P5233 概率博弈
Description 小A和小B在玩游戏.这个游戏是这样的: 有一棵n个点的以1为根的有根树,叶子有权值.假设有m个叶子,那么树上每个叶子的权值序列就是一个1->m 的排列. 一开始在1号点有 ...
- POJ 3342 树形DP+Hash
这是很久很久以前做的一道题,可惜当时WA了一页以后放弃了. 今天我又重新捡了起来.(哈哈1A了) 题意: 没有上司的舞会+判重 思路: hash一下+树形DP 题目中给的人名hash到数字,再进行运算 ...
- 0x54. 动态规划 - 树形DP(习题详解 × 12)
目录 0x54.1 树形DP Problem A. 没有上司的舞会 Problem B. 战略游戏 0x54.2 树上背包 Problem A. 选课 Problem B.[数据加强版]选课(树上背包 ...
- 【树形DP】树的重心详解+多组例题详解
目录 定义: 性质: 算法分析: POJ 1655 Balancing Act(求重心) POJ 3107 Godfather P1364 医院设置(树形DP) 定义: 树的重心也叫树的质心.对于一棵 ...
- 树形dp——树的重心(2) 代码调试理解
和树的最大独立问题类似,先任选一个结点作为根节点,把无根树变成有根树,然后设d(i)表示以i为根的子树的结点的个数.不难发现d(i)=∑d(j)+1,j∈s(i).s(i)为i结点的所有儿子结点的编号 ...
- [WC2018]通道——边分治+虚树+树形DP
题目链接: [WC2018]通道 题目大意:给出三棵n个节点结构不同的树,边有边权,要求找出一个点对(a,b)使三棵树上这两点的路径权值和最大,一条路径权值为路径上所有边的边权和. 我们按照部分分逐个 ...
- layui树形父子不关联_DP专题7 | 没有上司的舞会 洛谷1352(树形DP)
高能预警:这是一篇超过5分钟的学习文章,暑假了可以多学会 本篇继续咱们的DP专题,树形DP入门.动态规划每一个类型的DP都是深坑,期望童鞋们自己在这个系列的基础上多花时间进行拓展,学习愉快~ 在讨论树 ...
- 【BZOJ-1864】三色二叉树 树形DP
1864: [Zjoi2006]三色二叉树 Time Limit: 1 Sec Memory Limit: 64 MB Submit: 659 Solved: 469 [Submit][Statu ...
最新文章
- 赠书 | 算力时代,用 Python 来快速解决复杂问题
- python读取指定行的txt_【Python】读取txt文件,获取指定行中指定位置数据
- 【UGV】小车一些图片 麦轮版小车
- python并发编程调优_Python并发编程-并发解决方案概述
- 将Windows 8.1 系统窗口背景设置成淡绿色?
- 服务提供者和服务消费者
- 【NOIP2010】【P1317】乌龟棋
- Java代理模式——静态代理动态代理
- python连接mysql的一些基础知识+安装Navicat可视化数据库+flask_sqlalchemy写数据库
- 干货:结合Scikit-learn介绍几种常用的特征选择方法
- ref:PHP反序列化漏洞成因及漏洞挖掘技巧与案例
- 分布式光伏融资难点分析
- JavaWeb学习总结(一)JavaWeb入门与Tomcat
- HTML5 postMessage解决跨域|跨窗口通信
- 【6.10校内test】T3 加分二叉树
- 找出数组中第二大的值
- 使用jekins自动构建部署java maven项目(jdk1.7+tomcat7.0+jenkins2.19.3)
- 2020年居家实习日志
- java commons math_Apache Commons Math
- jpg怎么合成一份_如何将多张图片合成一个文件
热门文章
- 关于new String(new byte[]{0})
- APACHE利用Limit模块限制IP连接数
- grails 转为java_创建一个grails项目,然后转成maven项目
- python使用复合语句def创建函数对象_【收藏】Python实用技巧-成为Pythoner必经之路...
- 5GS 协议栈 — N1 接口的协议栈(NAS)
- PyQt4 Python GUI窗体应用程序
- CentOS6.5 升级 Python 2.7 版本
- 如何实现分享链接到微信朋友圈时显示自定义LOGO以及名称介绍
- 收藏:《Exchange 2013 OWA/ECP 登陆后白屏》
- openstack中glance组件images的全部python API 汇总