HDU 2586(LCA欧拉序和st表)

Posted luoyugongxi

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 2586(LCA欧拉序和st表)相关的知识,希望对你有一定的参考价值。

什么是欧拉序,可以去这个大佬的博客(https://www.cnblogs.com/stxy-ferryman/p/7741970.html)巨详细

因为欧拉序中的两点之间,就是两点遍历的过程,所以只要找遍历过程中对应的最小的深度就行了,这里用st表存,first存第一个u出现的地方,用value存欧拉序,同时用depth存对应深度

 

模板

技术图片
 1 struct node{
 2     int v,next,dist;
 3 }a[maxn<<1];
 4 int n,m,tot,len;
 5 int st[maxn<<1][20], depth[maxn<<1],value[maxn<<1],first[maxn<<1];
 6 int dist[maxn],head[maxn];
 7 void add(int u,int v,int dist0){
 8     a[tot].next=head[u];
 9     a[tot].dist=dist0;
10     a[tot].v=v;
11     head[u]=tot++;
12 }
13 void dfs(int u,int fa,int d) {
14     value[++len]=u;depth[len]=d;first[u]=len;
15     for (int i=head[u];~i;i=a[i].next){
16         int v=a[i].v;if(v==fa)continue;
17         dist[v]=dist[u]+a[i].dist;
18         dfs(v,u,d+1);
19         value[++len]=u;depth[len]=d;
20     }
21 }
22 inline void init(int n){
23     for(int i=0;i<=n;i++)head[i]=-1,depth[i]=0;
24     tot=0,len=0;
25 }
26 inline void makest(){
27     for(it i=1;i<=len;i++)st[i][0]=depth[i];
28     for(it i=1;1<<i<=len;i++){
29         for(it j=1;j+(1<<i)-1<=len;j++){
30             st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
31         }
32     }
33 }
34 inline int dis(int u,int v){
35     int l=first[u],r=first[v];
36     if(l>r){swap(l,r);}
37     int k=log2(r-l+1);
38     int dep=min(st[l][k],st[r-(1<<k)+1][k]);
39     return dist[u]+dist[v]-2*dist[value[first[dep]]];
40 }
View Code

 

题意:

以1为根的树,两个点之间的最近距离是多少

思路:

模板LCA

用欧拉序+st表

技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define il inline
 5 #define it register int
 6 #define inf 0x3f3f3f3f
 7 #define lowbit(x) (x)&(-x)
 8 #define mem(a,b) memset(a,b,sizeof(a))
 9 #define modd 998244353
10 const int maxn=4e4+10;
11 struct node{
12     int v,next,dist;
13 }a[maxn<<1];
14 int n,m,tot,len;
15 int st[maxn<<1][20], depth[maxn<<1],value[maxn<<1],first[maxn<<1];
16 int dist[maxn],head[maxn];
17 void add(int u,int v,int dist0){
18     a[tot].next=head[u];
19     a[tot].dist=dist0;
20     a[tot].v=v;
21     head[u]=tot++;
22 }
23 void dfs(int u,int fa,int d) {
24     value[++len]=u;depth[len]=d;first[u]=len;
25     for (int i=head[u];~i;i=a[i].next){
26         int v=a[i].v;if(v==fa)continue;
27         dist[v]=dist[u]+a[i].dist;
28         dfs(v,u,d+1);
29         value[++len]=u;depth[len]=d;
30     }
31 }
32 inline void init(int n){
33     for(int i=0;i<=n;i++)head[i]=-1,depth[i]=0;
34     tot=0,len=0;
35 }
36 inline void makest(){
37     for(it i=1;i<=len;i++)st[i][0]=depth[i];
38     for(it i=1;1<<i<=len;i++){
39         for(it j=1;j+(1<<i)-1<=len;j++){
40             st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
41         }
42     }
43 }
44 inline int dis(int u,int v){
45     int l=first[u],r=first[v];
46     if(l>r){swap(l,r);}
47     int k=log2(r-l+1);
48     int dep=min(st[l][k],st[r-(1<<k)+1][k]);
49     return dist[u]+dist[v]-2*dist[value[first[dep]]];
50 }
51 int main(){
52     int t;
53     scanf("%d",&t);
54     while(t--){
55         scanf("%d%d",&n,&m);
56         init(n);
57         for(it i=0;i<n-1;i++){int u,v,w;
58             scanf("%d%d%d",&u,&v,&w);
59             add(u,v,w);add(v,u,w);
60         }
61         dfs(1,0,1);
62         makest();
63         while(m--){
64             int l,r;
65             scanf("%d%d",&l,&r);
66             printf("%d
",dis(l,r));
67         }
68     }
69     return 0;
70 }
View Code

 

用倍增

技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define ll long long
 4 #define il inline
 5 #define it register int
 6 #define inf 0x3f3f3f3f
 7 #define lowbit(x) (x)&(-x)
 8 #define mem(a,b) memset(a,b,sizeof(a))
 9 #define modd 998244353
10 const int maxn=4e4+10;
11 struct node{
12     int v,next,dist;
13 }a[maxn<<1];
14 int n,m,tot;
15 int fath[maxn][20], depth[maxn];
16 int dist[maxn],head[maxn];
17 void add(int u,int v,int dist0){
18     a[tot].next=head[u];
19     a[tot].dist=dist0;
20     a[tot].v=v;
21     head[u]=tot++;
22 }
23 void dfs(int u,int fa,int d) {
24     fath[u][0]=fa; depth[u]=d;
25     for(int i=1;i<20;i++) fath[u][i]=fath[fath[u][i-1]][i-1];
26     for (int i=head[u];~i;i=a[i].next){
27         int v=a[i].v;if(v==fa)continue;
28         dist[v]=dist[u]+a[i].dist;
29         dfs(v,u,d+1);
30     }
31 }
32 void init(int n){
33     for(int i=0;i<=n;i++)fath[i][0]=0,dist[i]=0,head[i]=-1,depth[i]=0;
34     tot=0;
35 }
36 inline int lca(int x,int y){
37     if(depth[x]<depth[y])swap(x,y);
38     int h=depth[x]-depth[y];
39     for(it i=0;h>0;i++){
40         if(h&1){
41             x=fath[x][i];
42         }
43         h>>=1;
44     }
45     if(x==y)return x;
46     for(it i=19;i>=0;i--){
47         if(fath[x][i]!=fath[y][i]){
48             x=fath[x][i];
49             y=fath[y][i];
50         }
51     }
52     return fath[x][0];
53 }
54 inline int dis(int u,int v){
55     int d=lca(u,v);
56     return dist[u]+dist[v]-2*dist[d];
57 }
58 int main(){
59     int t;
60     scanf("%d",&t);
61     while(t--){
62         scanf("%d%d",&n,&m);
63         init(n);
64         for(it i=0;i<n-1;i++){int u,v,w;
65             scanf("%d%d%d",&u,&v,&w);
66             add(u,v,w);add(v,u,w);
67         }
68         dfs(1,0,1);
69         while(m--){
70             int l,r;
71             scanf("%d%d",&l,&r);
72             printf("%d
",dis(l,r));
73         }
74     }
75     return 0;
76 }
View Code

 

以上是关于HDU 2586(LCA欧拉序和st表)的主要内容,如果未能解决你的问题,请参考以下文章

HDU - 2586 How far away? 在线LCA ST算法

HDU2586.How far away ?-LCA(在线ST算法)

hdu 2586 How far away ?倍增LCA

hdu 2586 How far away ? 离线LCA

HDU2586How far away? LCA

hdu2586(LCA模板)