题目链接:

http://codeforces.com/problemset/problem/337/D

题目大意:

给一棵树,m个点,一个距离d,求有多少个点A,使得A到所有的m个点距离都不超过d.

解题思路:

树形dp.

有两种方法可以解:

1、类似于树的直径的求法,先以任意一点作为树根,找到距离该点最远的m中的A点(A点一定是m个点中距离相距最远的两点的一个端点),然后以A点作为树根,依次计算各点到A点的最短距离d1[],并找到距离最远的m中的点B点,然后以B点为树根,依次找到各点到B点的距离d2[].  最后再扫一遍,找到d1和d2都不超过d的点。这种方法求比较简单。

2、先以m中任意一点为树根,在子树中,求出每个节点到达m中的点的最大距离max1,达到max1的直接儿子pre,次大距离。然后再从该根出发,递归维护一个值从父亲过来并且不是通过该节点的最大距离。每次求儿子时判断下,是不是等于该节点的pre,如果是的话,从次大中找。

树很灵活,递归很强大。多做些树上的题。

代码:

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
#include<stack>
#include<list>
#include<queue>
#define eps 1e-6
#define INF 0x1f1f1f1f
#define PI acos(-1.0)
#define ll __int64
#define lson l,m,(rt<<1)
#define rson m+1,r,(rt<<1)|1
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;//freopen("data.in","r",stdin);
//freopen("data.out","w",stdout);
#define Maxn 110000
//
struct Node
{int max1,max2,pre; //只用保存在子树中,该点到给定点的最大距离、次大距离以及最大距离的直接儿子编号//向下推进的时候,维护一个从父亲到达该点的最大值
}node[Maxn];struct Edge
{int v;struct Edge *next;
}*head[Maxn<<1],edge[Maxn<<1]; //无向边
bool pm[Maxn];
int n,m,d,ans,cnt;void add(int a,int b)
{++cnt;edge[cnt].v=b;edge[cnt].next=head[a],head[a]=&edge[cnt];
}
void dfs1(int pre,int cur)
{if(pm[cur]) //如果是给定的点 距离为0,否则置为无穷大node[cur].max1=node[cur].max2=0;elsenode[cur].max1=node[cur].max2=-INF;struct Edge * p=head[cur];while(p){if(p->v!=pre){dfs1(cur,p->v);//先求出儿子if(node[p->v].max1+1>=node[cur].max1) //用儿子来更新最大值{node[cur].max2=node[cur].max1;//更新次大值node[cur].max1=node[p->v].max1+1;node[cur].pre=p->v;}else{  //更新次大值if(node[p->v].max1+1>node[cur].max2)node[cur].max2=node[p->v].max1+1;}}p=p->next;}
}
void dfs2(int pre,int cur,int pa) //往下递归的时候,顺便判断,决定出来
{if(max(node[cur].max1,pa)<=d) //从父亲和孩子的最大距离不超过d的话,肯定是可以的ans++;struct Edge * p=head[cur];while(p){if(p->v!=pre){if(p->v==node[cur].pre) //如果最大值是从该儿子更新过来的,从次大值中选dfs2(cur,p->v,max(node[cur].max2,pa)+1);elsedfs2(cur,p->v,max(node[cur].max1,pa)+1);}p=p->next;}
}int main()
{int a,b,aa;while(~scanf("%d%d%d",&n,&m,&d)){memset(pm,false,sizeof(pm));memset(head,NULL,sizeof(head));for(int i=1;i<=m;i++){scanf("%d",&a);pm[a]=true; //标记能够攻击的点}for(int i=1;i<n;i++){scanf("%d%d",&aa,&b);add(aa,b);add(b,aa);}ans=0;if(pm[1]) //如果是给定的m中点,从父亲过来的为0{dfs1(-1,1);dfs2(-1,1,0);}else //如果不是给定的m中的点,从父亲过来的为-INF{dfs1(-1,1);dfs2(-1,1,-INF);}// dfs1(-1,a);/* for(int i=1;i<=n;i++)printf("i:%d %d pre:%d\n",i,node[i].max1,node[i].pre);*/// dfs2(-1,a,0); //最后一个参数表示从父亲过来的最大距离,//注意不能从任意一点开始,因为从该点的父亲过来的不为0,为-INF.printf("%d\n",ans);}return 0;
}
/*
10 1 0
3
10 1
1 3
8 3
3 5
5 7
5 4
2 4
9 4
6 4
*/

树形dp-CF-337D. Book of Evil相关推荐

  1. cf 1060e 树形dp 树上任意两点的距离和

    题意: 给出一个树,把树上任意两个相隔一个点的点加一条边,问加完边之后任意两点的距离和是多少.   参考博客 :https://blog.csdn.net/Mr_Treeeee/article/det ...

  2. 【CF 543D】Road Improvement,树形DP

    传送门 题意: 给定一棵树,起初树边都是坏边,对于以节点ii为起点,你需要把一些坏边改成好边,使得从ii出发到达其他节点的路径上至多只有一条坏边,求每个节点ii的方案数 思路: 学习了一些新姿势 re ...

  3. *【HDU - 6201】transaction transaction transaction(树形dp 或 spfa最长路 或 网络流)

    题干: 题目大意: 给出一棵n个顶点的树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过所需要的花费.现在需要你在树上选择两个点,一个作为买入商品的点,一个作为卖出商品 ...

  4. 动态规划报告(树形DP+概率DP

    动态规划报告 树形dp 树形 DP,即在树上进行的 DP.由于树固有的递归性质,树形 DP 一般都是递归进行的.一般需要在遍历树的同时维护所需的信息 以一道题目为例 2022CCPC桂林站G Grou ...

  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到数字,再进行运算 ...

  10. [NC15748]旅游 树形dp基础

    菜鸡第一次接触树形dp这个东西,不过这个东西还是很好理解的(可能是因为模板题吧) 个人感觉,相比线性dp,树形dp的状态转移方程更加的直观,难点主要是在"树"的结构上比较麻烦. 题 ...

最新文章

  1. SimpleDateFormat 日期,时间格式转化
  2. U-NET 图像预处理
  3. uefi启动u盘安装系统_技嘉uefi启动怎么安装win8.1系统【安装教程】
  4. python取消任务的方法_python-即使忽略CancelledError,如何取消任务执...
  5. 35/100. Permutations
  6. 15. 3Sum-数组
  7. java 使用 new Date() 和 System.currentTimeMillis() 获取当前 时间戳
  8. 乒乓球十一分制比赛规则_乒乓球的基本比赛规则
  9. python语言基本语句例句-关于python:使用WordNet查找同义词,定义和例句
  10. (35) css企业命名规范
  11. 深度剖析python_汉诺塔问题深度剖析(python实现)
  12. SpringCloud工作笔记062---APP消息推送_个推平台API使用经验
  13. 记录自己在厦门两年来的面试经历--完结篇
  14. 2022年第十二届MathorCup高校数学建模挑战赛
  15. 数据分析师的薪资怎么样?
  16. Mysql SSL 2206错误
  17. qq发的html文件打不开,Win10系统下QQ能上网页却无法打开的三种解决方案
  18. 《英语语法新思维初级教程》学习笔记(九)进行时态
  19. openMP编程详解(囊括所有基本指令)
  20. 无线传输课程设计,基于ZigBee的水质监测系统设计

热门文章

  1. STM32F103ZET6 蜂鸣器、按键
  2. Linuxcurl命令参数详解
  3. ui设计未来十年前景_UI设计的10条诫命
  4. 如何优雅处理 async await 错误——解读小而美的 await-to-js 库
  5. thinkphp5多级控制器是什么?怎么使用?
  6. Linux内核 TCP/IP、Socket参数调优
  7. 新浪微博授权认证过程
  8. jQuery 基金会和 Dojo 基金会合并:Open Web
  9. vc++ mfc中拖动效果的实现 借助于CImageList
  10. LCD1602,4位数据总线液晶屏时钟,STC12C5A60S2的10位ADC功能程序