树形dp-CF-337D. Book of Evil
题目链接:
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;
else
node[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);
else
dfs2(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的更多相关文章
- CF 337D Book of Evil 树形DP 好题
Paladin Manao caught the trail of the ancient Book of Evil in a swampy area. This area contains n se ...
- codeforces 337D 树形DP Book of Evil
原题直通车:codeforces 337D Book of Evil 题意:一棵n个结点的树上可能存在一个Evil,Evil危险范围为d,即当某个点与它的距离x<=d时,那么x是危险的. 现已知 ...
- codeforces 337D Book of Evil (树形dp)
题目链接:http://codeforces.com/problemset/problem/337/D 参考博客:http://www.cnblogs.com/chanme/p/3265913 题目大 ...
- CF 219D 树形DP
CF 219D [题目链接]CF 219D [题目类型]树形DP &题意: 给一个n节点的有向无环图,要找一个这样的点:该点到其它n-1要逆转的道路最少,(边<u,v>,如果v要到 ...
- CF EDU 1101D GCD Counting 树形DP + 质因子分解
CF EDU 1101D GCD Counting 题意 有一颗树,每个节点有一个值,问树上最长链的长度,要求链上的每个节点的GCD值大于1. 思路 由于每个数的质因子很少,题目的数据200000&l ...
- CF 486D vailid set 树形DP
As you know, an undirected connected graph with n nodes and n - 1 edges is called a tree. You are gi ...
- CF 461B Appleman and Tree 树形DP
Appleman has a tree with n vertices. Some of the vertices (at least one) are colored black and other ...
- CF 219D Choosing Capital for Treeland 树形DP 好题
一个国家,有n座城市,编号为1~n,有n-1条有向边 如果不考虑边的有向性,这n个城市刚好构成一棵树 现在国王要在这n个城市中选择一个作为首都 要求:从首都可以到达这个国家的任何一个城市(边是有向的) ...
- CF 463A && 463B 贪心 && 463C 霍夫曼树 && 463D 树形dp && 463E 线段树
http://codeforces.com/contest/462 A:Appleman and Easy Task 要求是否全部的字符都挨着偶数个'o' #include <cstdio> ...
- CF F - Tree with Maximum Cost (树形DP)给出你一颗带点权的树,dist(i, j)的值为节点i到j的距离乘上节点j的权值,让你任意找一个节点v,使得dist(v, i) (1 < i < n)的和最大。输出最大的值。
题目意思: 给出你一颗带点权的树,dist(i, j)的值为节点i到j的距离乘上节点j的权值,让你任意找一个节点v,使得dist(v, i) (1 < i < n)的和最大.输出最大的值. ...
随机推荐
- [转] Linux TCP/IP网络小课堂:net-tools与iproute2大比较
PS:netstat选项是-planet,方便记忆 http://os.51cto.com/art/201409/450886.htm 如今许多系统管理员仍结合使用ifconfig.route.arp ...
- php5.2通过saprfc扩展远程连接sap730成功案例
公司刚上sap系统,由于资金有限,sap与其它系统的数据交换需要公司内部实现.于是,领导决定入库申请流程需要在sap与OA系统里实现电子签核流,重担果然落到我的身上.好在我只负责OA,还一位同事负责s ...
- asp.net中调用COM组件发布IIS时常见错误 80070005解决方案
很多人在.net开发Web站点中引用了COM组件,调试时一切正常,但一发布到IIS下就提示如下错误: 检索 COM 类工厂中 CLSID 为 {} 的组件时失败,原因是出现以下错误: 80070005 ...
- (转)DEDECMS 如何让栏目外部链接在新窗口中打开
近遇到一个问题,就是dedecms的导航,是用外部链接的,但是原窗口打开不好看,新窗口打开好点.OK,放狗... 1. 查找模板中的head.htm将<li><a href='[fi ...
- JavaScript--循环--打印星星和99乘法表
1.打印99乘法表 function chengfa(){ //反复调用公式 for(var r=1;r<=9;r++){ for(var i=1,str="";i<= ...
- [转]STL的内存分配器
题记:内存管理一直是C/C++程序的红灯区.关于内存管理的话题,大致有两类侧重点,一类是内存的正确使用,例如C++中new和delete应该成对出现,用RAII技巧管理内存资源,auto_ptr等方面 ...
- USACO5.4-TeleCowmunication
题目大意:给出一个无向图,要求删除尽量少的点,使给定的2点间不再连通,并输出字典序最小的方案题型:图论-网络流此题难点在于建图,后面就是套网络流的模板.将点看成边,例如第i个点可以看成一条有向边< ...
- windows 7下安装python+mongodb
1. python安装 下载:http://python.org/download/ 直接双击安装,安装完后将路径加入系统环境变量path中. 2. mongodb安装 下载:http://www.m ...
- html form <label>标签基础语法结构与使用案例教程(转载)
在表单布局中会遇到label标签的使用,label没有任何样式效果,有触发对应表单控件功能.比如我们点击单选按钮或多选框前文字对应选项就能被选中,这个就是对文字加了<label>标签实现. ...
- day06
一.configparser模块 configparser用于处理特定格式的文件,其本质上是利用open来操作文件 1.获取所有节点 import configparser config = conf ...