zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",dis(l,r));
            }
        }
        return 0;
    }
  • 相关阅读:
    apt常用命令(安装,更新,删除)
    记录一次坑爹的VM连接主机的路程
    VM安装centos
    初窥DB2之insert语句
    关于虚拟机的linux不能使用shell连接时的处理方法
    linux命令之查看字符集
    趣图:学JavaScript
    PHP搭建大文件切割分块上传功能示例
    判断变量是否不为空,函数isset()、!empty()与!is_null()的比较
    Javascript 中 null、NaN和undefined的区别
  • 原文地址:https://www.cnblogs.com/luoyugongxi/p/12347268.html
Copyright © 2011-2022 走看看