HDU 2586(LCA欧拉序和st表)

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

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

 st

倍增

模板

struct node{
    int v,next,dist;
}a[maxn<<1];
int n,m,tot,len;
int st[maxn<<1][20], depth[maxn<<1],value[maxn<<1],first[maxn<<1];
int dist[maxn],head[maxn];
void add(int u,int v,int dist0){
    a[tot].next=head[u];
    a[tot].dist=dist0;
    a[tot].v=v;
    head[u]=tot++;
}
void dfs(int u,int fa,int d) {
    value[++len]=u;depth[len]=d;first[u]=len;
    for (int i=head[u];~i;i=a[i].next){
        int v=a[i].v;if(v==fa)continue;
        dist[v]=dist[u]+a[i].dist;
        dfs(v,u,d+1);
        value[++len]=u;depth[len]=d;
    }
}
inline void init(int n){
    for(int i=0;i<=n;i++)head[i]=-1,depth[i]=0;
    tot=0,len=0;
}
inline void makest(){
    for(it i=1;i<=len;i++)st[i][0]=depth[i];
    for(it i=1;1<<i<=len;i++){
        for(it j=1;j+(1<<i)-1<=len;j++){
            st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
        }
    }
}
inline int dis(int u,int v){
    int l=first[u],r=first[v];
    if(l>r){swap(l,r);}
    int k=log2(r-l+1);
    int dep=min(st[l][k],st[r-(1<<k)+1][k]);
    return dist[u]+dist[v]-2*dist[value[first[dep]]];
}

 

 

题意:

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

思路:

模板LCA

用欧拉序+st表

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define mem(a,b) memset(a,b,sizeof(a))
#define modd 998244353
const int maxn=4e4+10;
struct node{
    int v,next,dist;
}a[maxn<<1];
int n,m,tot,len;
int st[maxn<<1][20], depth[maxn<<1],value[maxn<<1],first[maxn<<1];
int dist[maxn],head[maxn];
void add(int u,int v,int dist0){
    a[tot].next=head[u];
    a[tot].dist=dist0;
    a[tot].v=v;
    head[u]=tot++;
}
void dfs(int u,int fa,int d) {
    value[++len]=u;depth[len]=d;first[u]=len;
    for (int i=head[u];~i;i=a[i].next){
        int v=a[i].v;if(v==fa)continue;
        dist[v]=dist[u]+a[i].dist;
        dfs(v,u,d+1);
        value[++len]=u;depth[len]=d;
    }
}
inline void init(int n){
    for(int i=0;i<=n;i++)head[i]=-1,depth[i]=0;
    tot=0,len=0;
}
inline void makest(){
    for(it i=1;i<=len;i++)st[i][0]=depth[i];
    for(it i=1;1<<i<=len;i++){
        for(it j=1;j+(1<<i)-1<=len;j++){
            st[j][i]=min(st[j][i-1],st[j+(1<<(i-1))][i-1]);
        }
    }
}
inline int dis(int u,int v){
    int l=first[u],r=first[v];
    if(l>r){swap(l,r);}
    int k=log2(r-l+1);
    int dep=min(st[l][k],st[r-(1<<k)+1][k]);
    return dist[u]+dist[v]-2*dist[value[first[dep]]];
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        init(n);
        for(it i=0;i<n-1;i++){int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);add(v,u,w);
        }
        dfs(1,0,1);
        makest();
        while(m--){
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%d\n",dis(l,r));
        }
    }
    return 0;
}

 

 

用倍增

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define il inline
#define it register int
#define inf 0x3f3f3f3f
#define lowbit(x) (x)&(-x)
#define mem(a,b) memset(a,b,sizeof(a))
#define modd 998244353
const int maxn=4e4+10;
struct node{
    int v,next,dist;
}a[maxn<<1];
int n,m,tot;
int fath[maxn][20], depth[maxn];
int dist[maxn],head[maxn];
void add(int u,int v,int dist0){
    a[tot].next=head[u];
    a[tot].dist=dist0;
    a[tot].v=v;
    head[u]=tot++;
}
void dfs(int u,int fa,int d) {
    fath[u][0]=fa; depth[u]=d;
    for(int i=1;i<20;i++) fath[u][i]=fath[fath[u][i-1]][i-1];
    for (int i=head[u];~i;i=a[i].next){
        int v=a[i].v;if(v==fa)continue;
        dist[v]=dist[u]+a[i].dist;
        dfs(v,u,d+1);
    }
}
void init(int n){
    for(int i=0;i<=n;i++)fath[i][0]=0,dist[i]=0,head[i]=-1,depth[i]=0;
    tot=0;
}
inline int lca(int x,int y){
    if(depth[x]<depth[y])swap(x,y);
    int h=depth[x]-depth[y];
    for(it i=0;h>0;i++){
        if(h&1){
            x=fath[x][i];
        }
        h>>=1;
    }
    if(x==y)return x;
    for(it i=19;i>=0;i--){
        if(fath[x][i]!=fath[y][i]){
            x=fath[x][i];
            y=fath[y][i];
        }
    }
    return fath[x][0];
}
inline int dis(int u,int v){
    int d=lca(u,v);
    return dist[u]+dist[v]-2*dist[d];
}
int main(){
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        init(n);
        for(it i=0;i<n-1;i++){int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            add(u,v,w);add(v,u,w);
        }
        dfs(1,0,1);
        while(m--){
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%d\n",dis(l,r));
        }
    }
    return 0;
}

 

posted @ 2020-02-22 21:20  ouluy  阅读(242)  评论(0编辑  收藏  举报