hdu2586 lca模板(在线路径倍增)

这是基于二分搜索的,这个感觉更好写,利用任何整数可以由多个2^x次方数相加得到来进行向上路径倍增。

代码和思路一样,相比较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,head[100005],next[100005],point[100005],value[100005];
 7 int dis[100005],parent[100005][25],depth[100005];
 8 //距离根节点距离,某节点的向上走2^j的步节点,该时间深度
 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   parent[u][0]=pre;
20   depth[u]=deep;
21   for (int i=head[u];i;i=next[i])
22   {
23     int v=point[i],w=value[i];
24     if (v==pre) continue;
25     dfs(v,u,deep+1,d+w);
26   }
27 }
28 void double_build(int n)
29 {
30   int i,j; 
31   for (i=0;i+1<=20;i++)//路径倍增
32     for (j=1;j<=n;j++)
33       if (parent[j][i]<0) parent[j][i+1]=-1;
34       else parent[j][i+1]=parent[parent[j][i]][i];
35 }
36 int double_query(int u,int v)
37 {
38   int i;
39   if (depth[u]>depth[v]) swap(u,v);
40   for (i=0;i<=20;i++)
41     if ((depth[v]-depth[u])>>i&1)
42       v=parent[v][i];
43   if (u==v) return u;
44   for (i=20;i>=0;i--) //二进制拆分思想达到倍增
45     if (parent[u][i]!=parent[v][i])
46     {
47       u=parent[u][i];
48       v=parent[v][i];
49     }
50   return parent[u][0];
51 }
52 int main()
53 {
54   int T,m,x,y,z,i,n;
55   scanf("%d",&T);
56   while (T--)
57   {
58     scanf("%d%d",&n,&m);
59     now=0;
60     memset(head,0,sizeof(head));
61     for (i=1;i<n;i++)
62     {
63       scanf("%d%d%d",&x,&y,&z);
64       add(x,y,z); add(y,x,z);
65     }
66     dfs(1,-1,1,0);
67     double_build(n);
68     while (m--)
69     {
70       scanf("%d%d",&x,&y);
71       z=double_query(x,y);
72       printf("%d\n",dis[x]+dis[y]-2*dis[z]);//距离计算
73     }
74   }
75   return 0;
76 }

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

posted on 2015-02-06 21:13  xiao_xin  阅读(528)  评论(0编辑  收藏  举报

导航