【题解】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不去时的最大欢乐值, ...
随机推荐
- eth-trunk
------------恢复内容开始------------ 1.eth-trunk 是什么 *链路 聚合技术 2.做什么用的 *作为一种链路捆绑技术,可以把多个独立物理接口绑定在一起,作为一个大带宽 ...
- Visual Studio/VS中任务列表的妙用
一.任务列表开启方法 首先说下开启的方法:视图-任务列表,即可打开任务列表. 快捷键Ctrl+'\'+T,熟练了可以快速开启.注意,'\'键是回车键上面的'',不要按成了'/' 二.任务列表标签设置 ...
- Jekyll+GitHub Pages部署自己的静态Blog
混了这么久,一直想拥有自己的博客,通过jekyll和GitHub Pages捣腾出了自己的博客(https://www.ichochy.com) 一.安装jekyll 首先有安装Ruby的开发环境 运 ...
- JAVA基础——标识符和数据类型
注释 单行注释 // 多行注释 /* */ 文档注释 /***/ 标识符和关键字 所有的标识符都应该以字母(A-Z或者a-z),美元符号($),或者下划线(_)开始 首字符之后可以时字母(A-Z或者a ...
- [bug] PyCharm远程Spark集群:Java gateway process exited before sending its port number
原因 无法连接到集群上的java 解决 方法一: 在右上角Edit Configurations中,添加一条环境变量JAVA_HOME,值为远程机器上的java安装路径 方法二: 直接在代码里写上JA ...
- Linux服务之nginx服务篇四(配置https协议访问)
一.配置nginx支持https协议访问 编译安装nginx的时候需要添加相应的模块--with-http_ssl_module和--with-http_gzip_static_module(可通过/ ...
- python 如何让俩个对象相等及如何让俩个对象具有相同的id值
- C#解决WebClient不能下载https网页内容
在下载之前,执行以下代码即可: if (stUrl.Substring(0, 5) == "https") { // 解决WebClient不能通过https下载内容问题 Serv ...
- 开源项目核心商城(CoreShop)
帮小伙伴推一下他的开源项目作者是@大灰灰 核心商城(CoreShop)Beta 支持可视化布局的.Net小程序商城 [![star](https://gitee.com/CoreUnion/CoreS ...
- Supervisor 开始
Supervisor 是 Linux/Unix 操作系统上的进程管理工具.本文介绍了于 Ubuntu 18 上如何使用 Supervisor 开机启动.保活守护自己的服务进程. 安装 建议系统方式安装 ...