POJ 3162 Walking Race(树的直径+单调队列)
题目大意:对一棵树,求出从每个结点出发能到走的最长距离(每个结点最多只能经过一次),将这些距离按排成一个数组得到dis[1],dis[2],dis[3]……dis[n] ,在数列的dis中求一个最长的区间,使得区间中的最大值与最小值的差不超过m。
思路:先找出树的直径的两个端点来,那么树当中的其它节点能走的最大距离一定是到这个两个点当中的其中一个的。所以三遍bfs就可以求出来这个最远的距离,那么,这个最远的距离求出来之后再用两个单调队列来维护最大值和最小值。
/*************************************************************************
> File Name: poj_3162.cpp
> Author: Howe_Young
> Mail: 1013410795@qq.com
> Created Time: 2015年09月05日 星期六 14时00分47秒
************************************************************************/ #include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
const int maxn = 1e6 + ;
int tot, head[maxn];
struct Edge {
int to, next, w;
}edge[maxn * ];
typedef pair<int, int> pii;
int dis1[maxn], dis2[maxn], dis[maxn];
void init()
{
tot = ;
memset(head, -, sizeof(head));
}
void addedge(int u, int v, int w)
{
edge[tot].to = v;
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot++;
}
int pos, maxx;
bool vis[maxn];
void bfs(int u, int *dist)//从u点开始搜索到各个点的距离,保存在dist当中
{
maxx = ;
queue<pii> Q;
memset(vis, false, sizeof(vis));
pii cur, nex;
cur.first = u; cur.second = ;
vis[u] = true;
dist[u] = ;
Q.push(cur);
while (!Q.empty())
{
cur = Q.front();
Q.pop();
for (int i = head[cur.first]; i != -; i = edge[i].next)
{
int v = edge[i].to;
if (vis[v]) continue;
vis[v] = true;
nex.first = v; nex.second = cur.second + edge[i].w;
dist[v] = nex.second;
if (maxx < nex.second)
{
maxx = nex.second;
pos = v;//直径的一个端点保存在pos当中
}
Q.push(nex);
}
}
}
int Q_max[maxn], Q_min[maxn];
int n, m;
int solve()//用两个单调队列分别维护最大值和最小值
{
int ans = ;
int front1, front2, tail1, tail2, i, j;
front1 = front2 = ; tail1 = tail2 = ;
for (j = , i = ; i <= n; i++)
{
while (tail1 >= front1 && dis[Q_max[tail1]] <= dis[i]) tail1--;
Q_max[++tail1] = i; while (tail2 >= front2 && dis[Q_min[tail2]] >= dis[i]) tail2--;
Q_min[++tail2] = i; if (dis[Q_max[front1]] - dis[Q_min[front2]] > m)
{
ans = max(ans, i - j);
while (dis[Q_max[front1]] - dis[Q_min[front2]] > m)
{
j = min(Q_max[front1], Q_min[front2]) + ;
while (tail1 >= front1 && Q_max[front1] < j) front1++;
while (tail2 >= front2 && Q_min[front2] < j) front2++;
}
}
}
ans = max(ans, i - j);
return ans;
}
int main()
{
while (~scanf("%d %d", &n, &m))
{
int v, w;
init();
for (int i = ; i < n; i++)
{
scanf("%d %d", &v, &w);
addedge(i + , v, w);
addedge(v, i + , w);
}
bfs(, dis1);
bfs(pos, dis1);
bfs(pos, dis2);
for (int i = ; i <= n; i++)
dis[i] = max(dis1[i], dis2[i]);
printf("%d\n", solve());
}
return ;
}
POJ 3162 Walking Race(树的直径+单调队列)的更多相关文章
- POJ 3162 Walking Race(树形dp+单调队列 or 线段树)
http://poj.org/problem?id=3162 题意:一棵n个节点的树.有一个屌丝爱跑步,跑n天,第i天从第i个节点开始跑步,每次跑到距第i个节点最远的那个节点(产生了n个距离),现在要 ...
- HDU 4123 Bob’s Race 树的直径+单调队列
题意: 给定n个点的带边权树Q个询问. 以下n-1行给出树 以下Q行每行一个数字表示询问. 首先求出dp[N] :dp[i]表示i点距离树上最远点的距离 询问u, 表示求出 dp 数组中最长的连续序列 ...
- POJ 3162 Walking Race (树的直径,单调队列)
题意:给定一棵带边权的n个节点的树,首先要求出每个点的最长路,然后写成序列d[1],d[2]...d[n],然后求满足 区间最大值-区间最小值<=k 的最大区间长度为多少? 思路: 分两步进行: ...
- 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
题目描述 Walking RaceTime Limit: 10000MS Memory Limit: 131072KTotal Submissions: 4941 Accepted: 1252Case ...
- HDU 4123 Bob's Race:树的直径 + 单调队列 + st表
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4123 题意: 给你一棵树,n个节点,每条边有长度. 然后有m个询问,每个询问给定一个q值. 设dis[ ...
- HDU 4123(树的直径+单调队列)
Bob’s Race Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- POJ 3162 Walking Race 树形DP+线段树
给出一棵树,编号为1~n,给出数m 漂亮mm连续n天锻炼身体,每天会以节点i为起点,走到离i最远距离的节点 走了n天之后,mm想到知道自己这n天的锻炼效果 于是mm把这n天每一天走的距离记录在一起,成 ...
随机推荐
- openshif ssh proxy
最近google又被墙了.没办法 1:注册一个openshift账号.申请注册一个app,获取一个免费主机. https://www.openshift.com/ 2:去PuTTY官方网站下载pL ...
- IOS各类问题
1.The resource could not be loaded because the App Transport Security policy requires the use of a s ...
- HDU 1207
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1207 四柱汉诺塔问题 当 r = (sqrt(8*n+1)-1)/2 时, 存在 count = (n ...
- mysql的SQL_CALC_FOUND_ROWS 使用
mysql的SQL_CALC_FOUND_ROWS 使用 标签: sqlmysqltable 2007-02-27 11:40 5073人阅读 评论(0) 收藏 举报 分类: Mysql数据库技术( ...
- 应用SVN(CentOS中搭建SVN服务器)
简单介绍如何在虚拟机 CentOS 中,搭建 SVN 服务器. 软件版本信息 Vmware 10.0.0 build-1295980 CentOS 7.0-1406-x64 Java 1.7.0_67 ...
- NXP LPC11xx I2C Slave 从机程序
/**************************************************************************** * $Id:: i2cslave.c 363 ...
- Request.url用法
原文:Request.url用法 我們在開發網頁應用程式,時常需要去解析網址(Request.Url)的每個片段,進行一些判斷.例如說 "http://localhost:1897/News ...
- 数据结构(跳跃表):NOI 2004 郁闷的出纳员
郁闷的出纳员 [问题描述] OIER公司是一家大型专业化软件公司,有着数以万计的员工.作为一名出纳员,我的任务之一便是统计每位员工的工资.这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常, ...
- First Bad Version——LeetCode
You are a product manager and currently leading a team to develop a new product. Unfortunately, the ...
- CodeForces 595B
题目链接: http://codeforces.com/problemset/problem/595/B 题意: 有一个n位的电话号码,每位电话号码将分成n/k段,每段均为k个数,求出满足以下要求的电 ...