【题解】poj 3162 Walking Race 树形dp
题目描述
Walking Race
Time Limit: 10000MS Memory Limit: 131072K
Total Submissions: 4941 Accepted: 1252
Case Time Limit: 3000MS
Description
flymouse’s sister wc is very capable at sports and her favorite event is walking race. Chasing after the championship in an important competition, she comes to a training center to attend a training course. The center has N check-points numbered 1 through N. Some pairs of check-points are directly connected by two-way paths. The check-points and the paths form exactly a tree-like structure. The course lasts N days. On the i-th day, wc picks check-point i as the starting point and chooses another check-point as the finishing point and walks along the only simple path between the two points for the day’s training. Her choice of finishing point will make it that the resulting path will be the longest among those of all possible choices.
After every day’s training, flymouse will do a physical examination from which data will obtained and analyzed to help wc’s future training be better instructed. In order to make the results reliable, flymouse is not using data all from N days for analysis. flymouse’s model for analysis requires data from a series of consecutive days during which the difference between the longest and the shortest distances wc walks cannot exceed a bound M. The longer the series is, the more accurate the results are. flymouse wants to know the number of days in such a longest series. Can you do the job for him?
Input
The input contains a single test case. The test case starts with a line containing the integers N (N ≤ 10^{6}) and M (M < \10^{9}). Then follow N − 1 lines, each containing two integers fi and di (i \= 1, 2, …, N − 1), meaning the check-points i + 1 and fi are connected by a path of length di.
Output
Output one line with only the desired number of days in the longest series.
Sample Input
3 2
1 1
1 3
Sample Output
3
题目大意
题目大概是给一棵n个结点边带权的树,记结点i到其他结点最远距离为d[i],问d数组构成的这个序列中满足其中最大值与最小值的差不超过m的连续子序列最长是多长。
思路
各个结点到其他结点的最远距离可以用树形DP解决,HDU2196
因为有最大值和最小值,需要两个单调队列,一个维护最大值qmax,另一个维护最小值qmin
具体操作看代码
代码
#include<cmath>
#include<deque>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register int
using namespace std;
inline int read(){
int x=0,w=1;
char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') w=-1,ch=getchar();
while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-48,ch=getchar();
return x*w;
}
const int MAXN=1e6+200;
struct edge {
int to,next,w;
} edges[MAXN*2];
int tot,dis[MAXN];
int head[MAXN];
void add_edge(int u,int v,int w) {
edges[tot].to=v;
edges[tot].w=w;
edges[tot].next = head[u];
head[u] = tot++;
}
int dist[MAXN][3]; //dist[i][0,1,2]分别为正向最大距离,正向次大距离,反向最大距离
int longest[MAXN];
int dfs1(int u,int fa) {
if(dist[u][0]>=0) return dist[u][0];
dist[u][0]=dist[u][1]=dist[u][2]=longest[u]=0;
for(re i=head[u];i!=-1;i=edges[i].next) {
int v=edges[i].to;
if(v==fa) continue;
if(dist[u][0]<dfs1(v,u)+edges[i].w) {
longest[u]=v;
dist[u][1]=max(dist[u][1],dist[u][0]);
dist[u][0]=dfs1(v,u)+edges[i].w;
}
else if(dist[u][1]<dfs1(v,u)+edges[i].w)
dist[u][1]=max(dist[u][1],dfs1(v,u)+edges[i].w);
}
return dist[u][0];
} void dfs2(int u,int fa) {
for(int i=head[u];i!=-1;i=edges[i].next) {
int v = edges[i].to;
if(v==fa)continue;
if(v==longest[u]) dist[v][2]=max(dist[u][2],dist[u][1])+edges[i].w;
else dist[v][2]=max(dist[u][2],dist[u][0])+edges[i].w;
dfs2(v,u);
}
} int finish(int n,int M){
if(n <= 0) return n;
if(M < 0) return 0;
deque<int> qmax,qmin; //qmax单调递减 qmin单调递增
deque<int> idmax,idmin; //id存节点编号(同样单调)
int ans=0;
int left=1,right=1;
while(right <= n){
//维护单调性
while(!qmax.empty() && dis[right] >= qmax.back()) qmax.pop_back(), idmax.pop_back();
qmax.push_back(dis[right]); idmax.push_back(right);
while(!qmin.empty() && dis[right] <= qmin.back()) qmin.pop_back(), idmin.pop_back();
qmin.push_back(dis[right]); idmin.push_back(right);
while(qmax.front()-qmin.front() > M && left<right){ //超出m就减少最大值/增大最小值(左指针右移)
left++;
while(idmax.front() < left) idmax.pop_front(), qmax.pop_front();
while(idmin.front() < left) idmin.pop_front(), qmin.pop_front();
}
ans = max(ans,right-left+1);
right++;
}
return ans;
}
int main() {
int n,m;
while(scanf("%d%d",&n,&m)==2&&n) {
tot=0;
memset(dist,-1,sizeof(dist));
memset(head,-1,sizeof(head));
memset(longest,-1,sizeof(longest));
for(int i=2; i<=n; i++) {
int v,w;
scanf("%d%d",&v,&w);
add_edge(i,v,w);
add_edge(v,i,w);
}
dfs1(1,-1);
dfs2(1,-1);
for(int i=1;i<=n;i++) dis[i]=max(dist[i][0],dist[i][2]);
printf("%d\n",finish(n,m));
}
return 0;
}
【题解】poj 3162 Walking Race 树形dp的更多相关文章
- POJ 3162.Walking Race 树形dp 树的直径
Walking Race Time Limit: 10000MS Memory Limit: 131072K Total Submissions: 4123 Accepted: 1029 Ca ...
- POJ - 3162 Walking Race 树形dp 单调队列
POJ - 3162Walking Race 题目大意:有n个训练点,第i天就选择第i个训练点为起点跑到最远距离的点,然后连续的几天里如果最远距离的最大值和最小值的差距不超过m就可以作为观测区间,问这 ...
- POJ 3162 Walking Race 树形DP+线段树
给出一棵树,编号为1~n,给出数m 漂亮mm连续n天锻炼身体,每天会以节点i为起点,走到离i最远距离的节点 走了n天之后,mm想到知道自己这n天的锻炼效果 于是mm把这n天每一天走的距离记录在一起,成 ...
- POJ 3162 Walking Race 树形dp 优先队列
http://poj.org/problem?id=3162 题意 : 一棵n个节点的树.wc爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要 ...
- POJ 3162 Walking Race(树形dp+单调队列 or 线段树)
http://poj.org/problem?id=3162 题意:一棵n个节点的树.有一个屌丝爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要 ...
- 【POJ3162】Walking Race 树形dp+单调队列+双指针
题目大意:给定一棵 N 个节点的无根树,边有边权,现生成一个序列 d,d[i] 表示 i 号节点到树上其他节点距离的最大值.给定一个 m,求 d 序列中最大值和最小值之差不超过 m 的最长连续段的长度 ...
- POJ 3162 Walking Race(树的直径+单调队列)
题目大意:对一棵树,求出从每个结点出发能到走的最长距离(每个结点最多只能经过一次),将这些距离按排成一个数组得到dis[1],dis[2],dis[3]……dis[n] ,在数列的dis中求一个最长的 ...
- POJ 3162 Walking Race (树的直径,单调队列)
题意:给定一棵带边权的n个节点的树,首先要求出每个点的最长路,然后写成序列d[1],d[2]...d[n],然后求满足 区间最大值-区间最小值<=k 的最大区间长度为多少? 思路: 分两步进行: ...
- poj 2324 Anniversary party(树形DP)
/*poj 2324 Anniversary party(树形DP) ---用dp[i][1]表示以i为根的子树节点i要去的最大欢乐值,用dp[i][0]表示以i为根节点的子树i不去时的最大欢乐值, ...
随机推荐
- @Scheduled 实现定时任务
@Scheduled注解实现定时任务 一.创建一个Springboot项目在启动类里加上@EnableScheduling 二.在写的定时任务的类上加上@Component把该类交由springboo ...
- 『居善地』接口测试 — 4、Requests库发送GET请求
目录 1.使用Requests库发送带参数的GET请求 2.查看GET请求的内容 3.带请求头.参数的Get请求 Requests库GET请求是使用HTTP协议中的GET请求方式对目标网站发起请求. ...
- JPEG头部解析
6.3 JPEG格式 6.3.1简介 微处理机中的存放顺序有正序(big endian)和逆序(little endian)之分.正序存放就是高字节存放在前低字节在后,而逆序存放就是低字 ...
- [刷题] 235 Lowest Common Ancestor of a Binary Search Tree
要求 给定一棵二分搜索树和两个节点,寻找这两个节点的最近公共祖先 示例 2和8的最近公共祖先是6 2和4的最近公共祖先是2 思路 p q<node node<p q p<=node& ...
- CSS元素的盒类型
一.css简介 CSS是Cascading Style Sheet的缩写,中文称层叠样式表.HTML中的元素都有着自己的属性和默认样式,CSS控制HTML内标签显示不同布局样式.控制对应html标签颜 ...
- python类变量的分类和调用方式
#!/usr/bin/python # -*- coding: UTF-8 -*- # 父类 class JustCounter: ''' 类变量:类变量在整个实例化的对象中是公用的.类变量定义在类中 ...
- 选择“保留window设置、个人文件及应用”或者“升级安装windows并保留文件设置和应用程序”的 处理干净以后用ghost备份
个人经验 第一次装好以后 把所有常用软件什么的 还有系统的更新全部装好 删去乱七八糟的临时文件啊什么的 处理干净以后用ghost备份下次需要重装直接从ghost镜像恢复 然后更新软件 打补丁 再备份 ...
- SSH自动断开连接的原因-20200323
SSH自动断开连接的原因 方法一: 用putty/SecureCRT连续3分钟左右没有输入, 就自动断开, 然后必须重新登陆, 很麻烦. 在网上查了很多资料, 发现原因有多种, 环境变量TMOUT ...
- C++知识点案例 笔记-2
1.友元函数 2.友元类 3.继承(公有继承) 4.公有继承的访问权限 5.私有继承的访问权限 6.保护继承的访问权限(两次继承) ==友元函数== #include <iostream> ...
- 常用Python第三方库简介
如果说强大的标准库奠定了Python发展的基石,丰富的第三方库则是python不断发展的保证,随着python的发展一些稳定的第三库被加入到了标准库里面,这里有6000多个第三方库的介绍 下表中加粗并 ...