1. 程式人生 > >hdu 4123--Bob’s Race(樹形DP+RMQ)

hdu 4123--Bob’s Race(樹形DP+RMQ)

算法 cas pid name col str possible 要求 choose

題目鏈接

Problem Description Bob wants to hold a race to encourage people to do sports. He has got trouble in choosing the route. There are N houses and N - 1 roads in his village. Each road connects two houses, and all houses are connected together. To make the race more interesting, he requires that every participant must start from a different house and run AS FAR AS POSSIBLE without passing a road more than once. The distance difference between the one who runs the longest distance and the one who runs the shortest distance is called “race difference” by Bob. Bob does not want the “race difference”to be more than Q. The houses are numbered from 1 to N. Bob wants that the No. of all starting house must be consecutive. He is now asking you for help. He wants to know the maximum number of starting houses he can choose, by other words, the maximum number of people who can take part in his race.

Input There are several test cases.
The first line of each test case contains two integers N and M. N is the number of houses, M is the number of queries.
The following N-1 lines, each contains three integers, x, y and z, indicating that there is a road of length z connecting house x and house y.
The following M lines are the queries. Each line contains an integer Q, asking that at most how many people can take part in Bob’s race according to the above mentioned rules and under the condition that the“race difference”is no more than Q.

The input ends with N = 0 and M = 0.

(N<=50000 M<=500 1<=x,y<=N 0<=z<=5000 Q<=10000000)

Output For each test case, you should output the answer in a line for each query.

Sample Input 5 5 1 2 3 2 3 4 4 5 3 3 4 2 1 2 3 4 5 0 0

Sample Output 1 3 3 3 5 題意:有一顆樹有n個節點編號從1~n,這n-1條邊都有一個邊權表示兩點之間的距離,現在要求出從每個點出發不重復經過同一條邊能到達的最遠距離,然後m次詢問,每次輸入一個Q,求從連續編號的起點出發達到最遠距離之間的最大值和最小值之差小於等於Q的最大區間長? 思路:用前向星建樹(定1號節點為根節點),一次搜索求出所有節點 以當前節點為根節點時到達子樹葉子節點的最遠距離和次遠距離,然後再進行一次搜索求出每個節點能到達的最遠距離(可能是到孩子葉子節點,也可能是經過父親節點而來的葉子節點),最後用RMQ中的ST算法配合尺取求出滿足條件的最大區間長。 註意:使用ST算法,查詢時不要使用函數log2(x),這個很費時間,自己求就行;另外可以優化一下尺取。 代碼如下:
#include <iostream>
#include 
<algorithm> #include <cstdio> #include <cstring> using namespace std; typedef long long LL; const int N=50005; int h[N],H[N],H2[N],ans[N],tot; int f1[N][20],f2[N][20]; struct edge { int to; int next; int x; }e[2*N]; void add(int u,int v,int x) { e[tot].to=v; e[tot].x=x; e[tot].next=h[u]; h[u]=tot++; e[tot].to=u; e[tot].x=x; e[tot].next=h[v]; h[v]=tot++; } void getH(int id,int fa) { H[id]=0; H2[id]=0; for(int i=h[id];i!=-1;i=e[i].next) { if(e[i].to==fa) continue; getH(e[i].to,id); int tmp=H[e[i].to]+e[i].x; if(H[id]<tmp) { H2[id]=H[id]; H[id]=tmp; } else if(H2[id]<tmp) H2[id]=tmp; } } void dfs(int id,int fa,int deep) { ans[id]=max(deep,H[id]); for(int i=h[id];i!=-1;i=e[i].next) { if(e[i].to==fa) continue; int tmp=deep; int d=H[e[i].to]+e[i].x; if(d==H[id]) tmp=max(tmp,H2[id]); else tmp=max(tmp,H[id]); dfs(e[i].to,id,tmp+e[i].x); } } void cal(int n) { for(int i=1;i<=n;i++) f1[i][0]=ans[i],f2[i][0]=ans[i]; int len=2; for(int s=1;len<=n;s++,len*=2) { for(int i=1;i+len-1<=n;i++) { f1[i][s]=max(f1[i][s-1],f1[i+len/2][s-1]); f2[i][s]=min(f2[i][s-1],f2[i+len/2][s-1]); } } } int get(int i,int j) { int len=-1; int t=j-i+1; while(t) { len++; t>>=1; } return max(f1[i][len],f1[j-(1<<len)+1][len])-min(f2[i][len],f2[j-(1<<len)+1][len]); } void init() { tot=0; memset(h,-1,sizeof(h)); } int main() { int n,m; while(scanf("%d%d",&n,&m)&&(n+m)) { init(); for(int i=1;i<n;i++) { int u,v,x; scanf("%d%d%d",&u,&v,&x); add(u,v,x); } getH(1,-1); dfs(1,-1,0); cal(n); while(m--) { int Q; scanf("%d",&Q); int res=0; int pos=1; for(int i=1;i<=n;i++) { if(i-pos+1<=res) continue; ///優化一下; int tmp=get(pos,i); while(tmp>Q) { pos++; tmp=get(pos,i); } res=max(res,i-pos+1); } printf("%d\n",res); } } return 0; } /** 4 6 1 2 2 1 3 4 3 4 3 */ /** 18 7984 1 2 2 1 3 4 1 4 3 1 5 5 2 6 1 2 7 3 2 8 7 3 9 2 3 10 4 4 11 2 4 12 2 5 13 3 5 14 3 9 15 7 9 16 6 12 17 5 14 18 4 */

hdu 4123--Bob’s Race(樹形DP+RMQ)