• lca 在线算法 zoj 3195


    题目链接:Design the city

    题目大意是对给定3点,求这三个点只之间的最短距离。三个点两两组合求lca:dis[u]+dis[v]-dis[lca];将三个组合值相加除以2即为答案。

    RMQ算法学习:http://blog.csdn.net/liang5630/article/details/7917702

    对于lca->RMQ的转化,可以参看巨巨写的ppt。

    欧拉序列:euler[N];

    深度序列:depth[N];

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    const int maxn=50000+10;
    const int M=20;
    int n,tot,T;
    int vis[maxn],euler[maxn<<1],depth[maxn<<1],pos[maxn],bit[M],head[maxn],dis[maxn];
    int dp[maxn<<1][M];
    struct node
    {
        int v,w,next;
    }e[maxn<<1];
    inline void Swap(int &a,int &b)
    {
        int c;
        c=a;
        a=b;
        b=c;
    }
    void build(int u,int v,int w)
    {
        e[T].v=v;
        e[T].w=w;
        e[T].next=head[u];
        head[u]=T++;
    }
    void init()
    {
        memset(vis,0,sizeof(vis));
        memset(head,-1,sizeof(head));
        memset(dis,0,sizeof(dis));
        T=0;
        tot=0;
        int u,v,w;
        for(int i=0;i<n-1;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            build(u,v,w);
            build(v,u,w);
        }
    }
    void dfs(int u,int dep)
    {
        vis[u]=1;
        euler[++tot]=u;
        pos[u]=tot;
        depth[tot]=dep;
        for(int i=head[u];~i;i=e[i].next)
        {
            int v=e[i].v;
            if(!vis[v])
            {
                int v=e[i].v;
                dis[v]=dis[u]+e[i].w;
                dfs(v,dep+1);
                euler[++tot]=u;
                depth[tot]=dep;
            }
    
        }
    }
    void ST(int len)
    {
        int k=(int)(log(len*1.0)/log(2.0));
        for(int i=1;i<=len;i++)
            dp[i][0]=i;
        for(int j=1;j<=k;j++)
        {
            for(int i=1;i+bit[j]<=len;i++)
            {
                int l=dp[i][j-1];
                int r=dp[i+bit[j-1]][j-1];
                dp[i][j]=depth[l]<depth[r]?l:r;
            }
        }
    }
    int RMQ(int x,int y)
    {
        int k=(int)(log((y-x+1)*1.0)/log(2.0));
        int l=dp[x][k];
        int r=dp[y-bit[k]+1][k];
        return depth[l]<depth[r]?l:r;
    }
    int LCA(int u,int v)
    {
        int l=pos[u];
        int r=pos[v];
        if(l>r)
            Swap(l,r);
        int res=RMQ(l,r);
        return euler[res];
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        for(int i=0;i<=M;i++)
            bit[i]=1<<i;
        int kase=0;
        while(~scanf("%d",&n))
        {
            if(kase!=0)
                printf("
    ");
            kase++;
            init();
            dfs(0,1);
            ST(2*n-1);
            int q;
            scanf("%d",&q);
            int a,b,c,lca[3],p;
            while(q--)
            {
                scanf("%d%d%d",&a,&b,&c);
                p=LCA(a,b);
                lca[0]=dis[a]+dis[b]-2*dis[p];
                p=LCA(b,c);
                lca[1]=dis[b]+dis[c]-2*dis[p];
                p=LCA(a,c);
                lca[2]=dis[a]+dis[c]-2*dis[p];
                printf("%d
    ",(lca[0]+lca[1]+lca[2])/2);
            }
        }
        return 0;
    }
    不为失败找借口,只为成功找方法
  • 相关阅读:
    使用auto_prepend_file和auto_append_file
    maven导入外部jar包的方法
    scala的多种集合的使用(3)之遍历集合的方法
    scala的多种集合的使用(4)之列表List(ListBuffer)的操作
    scala的多种集合的使用(2)之集合常用方法
    UltraEdit文本行数多变一和一边多
    scala的多种集合的使用(1)之集合层级结构与分类
    用Case类生成模板代码
    寻:IE总弹出广告窗口方法? Hello
    ASP.net中提示"分析器错误""未能加载类型" Hello
  • 原文地址:https://www.cnblogs.com/youmi/p/4517487.html
Copyright © 2020-2023  润新知