hdu2586 lca模板(在线RMQ)

杭电这题在线rmq用C++交会RE,G++才能过,但是手动开个栈C++就能AC了。。

在线RMQ用的一种倍增思想,还是很常见的,必然要熟练运用

数组具体功能代码里面都有:

dis[N] 距离根节点距离

id[N] 节点映射到dfs时间序上

doit[X] 时间点对应的原节点

depth[X] 该时间点深度

RMQ中:evalue[x][j] 于x起点2^j长度深度最小值  epoint[x][j] 于x起点2^j长度深度最小值时的节点

基于RMQ的在线lca思想:一遍dfs时间戳上述几个数组,然后利用RMQ预处理==

 1 #pragma comment(linker,"/STACK:16777216")
 2 #include<stdio.h>
 3 #include<string.h>
 4 #include<algorithm>
 5 using namespace std;
 6 int now,time_,head[100005],next[100005],point[100005],value[100005];
 7 int dis[100005],id[100005],doit[100005],depth[100005];
 8 //距离根节点距离,映射到dfs序上的时间,这个时间的原节点,该时间深度
 9 void add(int x,int y,int z)
10 {
11   next[++now]=head[x];
12   head[x]=now;
13   point[now]=y;
14   value[now]=z;
15 }
16 void dfs(int u,int pre,int deep,int d)
17 {
18   dis[u]=d;
19   id[u]=++time_;
20   doit[time_]=u;
21   depth[time_]=deep;
22   for (int i=head[u];i;i=next[i])
23   {
24     int v=point[i],w=value[i];
25     if (v==pre) continue;
26     dfs(v,u,deep+1,d+w);
27     doit[++time_]=u;
28     depth[time_]=deep;
29   }
30 }
31 int epoint[100005][20],evalue[100005][20];
32 void rmq_build(int x)
33 {
34   int i,j;
35   for (i=1;i<=x;i++)
36   {
37     epoint[i][0]=doit[i];//为了返回最小值对应原树中下标
38     evalue[i][0]=depth[i];//为了找出在处理时间序内的深度最小
39   }
40   for (j=1;(1<<j)<=x;j++)
41     for (i=1;i+(1<<j)-1<=x;i++)
42     {
43       evalue[i][j]=min(evalue[i][j-1],evalue[i+(1<<(j-1))][j-1]);
44       epoint[i][j]=evalue[i][j-1]<evalue[i+(1<<(j-1))][j-1]?
45         epoint[i][j-1]:epoint[i+(1<<(j-1))][j-1];
46     }
47 }
48 int rmq_query(int l,int r)
49 {
50   int k=0;
51   while ((1<<(k+1))<=r-l+1) k++;
52   return evalue[l][k]<evalue[r-(1<<k)+1][k]?
53     epoint[l][k]:epoint[r-(1<<k)+1][k];
54 }
55 int main()
56 {
57   int T,m,x,y,z,i,n;
58   scanf("%d",&T);
59   while (T--)
60   {
61     scanf("%d%d",&n,&m);
62     now=time_=0;
63     memset(head,0,sizeof(head));
64     for (i=1;i<n;i++)
65     {
66       scanf("%d%d%d",&x,&y,&z);
67       add(x,y,z); add(y,x,z);
68     }
69     dfs(1,-1,1,0);
70     rmq_build(2*n-1);
71     while (m--)
72     {
73       scanf("%d%d",&x,&y);
74       z=rmq_query(min(id[x],id[y]),max(id[x],id[y]));
75       //转化为工作时间序进入rmq
76    printf("%d\n",dis[x]+dis[y]-2*dis[z]);//距离计算
77     }
78   }
79   return 0;
80 }

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586

posted on 2015-02-06 20:14  xiao_xin  阅读(154)  评论(0编辑  收藏  举报

导航