本文主要是介绍POJ3162-Walking Race,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
题目:
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 Ndays. 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 ≤ 106) and M (M < 109). Then follow N − 1 lines, each containing two integers fi and di (i = 1, 2, …, N − 1), meaning the check-points i + 1 and fiare 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
Hint
Explanation for the sample:
There are three check-points. Two paths of lengths 1 and 3 connect check-points 2 and 3 to check-point 1. The three paths along with wc walks are 1-3, 2-1-3 and 3-1-2. And their lengths are 3, 4 and 4. Therefore data from all three days can be used for analysis.
题目大意:
给定一棵树,对于这棵树从1到n的每一个结点,在树上都能找到一个距离它最远的结点,记录从1到n这n个结点的最长距离dis[i],要求一段区间,满足这段区间内dis的最大值与最小值之差小于等于m,求这一段连续区间最长能是多长。
解题思路:
先用树形DP求出每个点能到达的最远距离,然后再使用两个单调队列,一个维护最大值,一个维护最小值,这样就能求出最长区间了。
树形DP求最远距离:两次dfs,一次由叶子转移到树根,一次由树根转移到叶子。
第一次dfs求出该结点到它的子节点的最远距离。
第二次dfs求出从该结点向上走能到达的最远距离。
对于第二次dfs的向上走,我们有可能在往上走k个结点之后,就又开始往下走,那往上走是只有唯一一条路径的,那么这段路径能求出来,而往下走的最远距离,就能用到我们第一次dfs求得的该结点的最远距离了。十分巧妙
#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<map>
#include<queue>using namespace std;
const long long inf = 0x3f3f3f3f3f3f3f3f;
const int maxn = 1000005;int n, m, k;struct Edge
{int to,nxt;long long w;
} edges[maxn<<2];
int head[maxn<<2];
int tot;void addEdge(int u, int v, long long w)
{edges[tot] = Edge{v,head[u],w};head[u] = tot++;
}long long dp1[maxn]; //从该结点往下走能走的最远距离
long long dp2[maxn]; //从该节点往上走能走的最远距离void dfs1(int u, int fa)
{for(int i = head[u]; ~i; i = edges[i].nxt){int to = edges[i].to;long long w = edges[i].w;if(to == fa)continue;dfs1(to,u);dp1[u] = max(dp1[u],dp1[to]+w);}
}void dfs2(int u, int fa, int ancestor, long long d) //当前结点,当前结点父亲,当前结点爷爷,父亲到当前点距离
{dp2[u] = dp2[fa];for(int i = head[fa]; ~i; i = edges[i].nxt){int to = edges[i].to;long long w = edges[i].w;if(to == u||to==ancestor)continue;dp2[u] = max(dp2[u],w+dp1[to]);}dp2[u]+=d;for(int i = head[u]; ~i; i = edges[i].nxt){int v = edges[i].to;long long w = edges[i].w;if(v == fa) continue;dfs2(v,u,fa,w);}
}long long qb[maxn];
long long qs[maxn];int main()
{int n;long long m;scanf("%d%lld", &n, &m);int u, v;long long w;memset(head,-1,sizeof(head));tot = 1;for(u = 2; u <= n; u++){scanf("%d%lld", &v, &w);addEdge(u,v,w);addEdge(v,u,w);}dfs1(1,0);dfs2(1,0,-1,0);for(int i = 1; i <= n; i++){dp1[i] = max(dp1[i],dp2[i]);
// cout << dp1[i]<<" ";}
// cout <<endl;int headb = 1,tailb = 0, heads = 1, tails = 0;int ans = 0;int minn = 0;for(int i = 1; i <= n; i++){while(tailb>=headb&&dp1[i]>dp1[qb[tailb]])tailb--;qb[++tailb] = i;while(tails>=heads&&dp1[i]<dp1[qs[tails]])tails--;qs[++tails] = i;while(dp1[qb[headb]]-dp1[qs[heads]]>m){minn = min(qb[headb],qs[heads]);if(minn == qb[headb])headb++;if(minn == qs[heads])heads++;}ans = max(ans,i-minn);}printf("%d\n", ans);return 0;
}7 4
1 8
1 4
2 2
2 3
3 6
3 3
这篇关于POJ3162-Walking Race的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!