zoukankan      html  css  js  c++  java
  • HDU 2586

      一道LCA的练手题。

      题目大意,在一个树中给出每两点之间的距离,然后让你求任意两点间的距离。

      很明显这可以用树剖(但是我不会),但是因为这里没有涉及到修改,我们可以巧妙的利用LCA来解决这个问题

      记一个点x到树根的距离为dis[x],另一个店y到树根的距离为dis[y],运用一下简单的容斥原理就可以知道x,y之间的最短路为:dis[x]+dis[y]-2*dis[LCA(x,y)]

      所以我们用Tarjan(倍增,DFS序+RMQ也行)预处理出所有的dis值以及每一对x,y的LCA,在询问的时候O(1)查询即可。

      预处理的复杂度为O(n α(n)),后面那个是并查集的复杂度

      CODE

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=40005;
    struct edge
    {
        int to,next,v;
    }e[N];
    struct ques
    {
        int to,next,num;
    }q[N];
    struct data
    {
        int x,y,fa;
    }a[N];
    int t,n,m,i,k,qk,x,y,z,root,father[N],dis[N],head[N],qhead[N],ru[N];
    bool vis[N];
    inline void read(int &x)
    {
        x=0; char ch=getchar();
        while (ch<'0'||ch>'9') ch=getchar();
        while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    }
    inline void write(int x)
    {
        if (x/10) write(x/10);
        putchar(x%10+'0');
    }
    inline void add(int x,int y,int z)
    {
        e[++k].to=y; e[k].v=z; e[k].next=head[x]; head[x]=k;
    }
    inline void qadd(int x,int y,int z)
    {
        q[++qk].to=y; q[qk].num=z; q[qk].next=qhead[x]; qhead[x]=qk;
    }
    inline int getfather(int k)
    {
        return father[k]==k?k:father[k]=getfather(father[k]);
    }
    inline void DFS(int now)
    {
        for (int i=head[now];i!=-1;i=e[i].next)
        dis[e[i].to]=dis[now]+e[i].v,DFS(e[i].to);
    }
    inline void LCA(int now)
    {
        vis[now]=1;
        for (int i=qhead[now];i!=-1;i=q[i].next)
        if (vis[q[i].to]) a[q[i].num].fa=getfather(q[i].to);
        for (int i=head[now];i!=-1;i=e[i].next)
        LCA(e[i].to),father[e[i].to]=now;
    }
    int main()
    {
        read(t);
        while (t--)
        {
            memset(head,-1,sizeof(head));
            memset(e,-1,sizeof(head));
            memset(qhead,-1,sizeof(qhead));
            memset(q,-1,sizeof(q));
            memset(ru,0,sizeof(ru));
            memset(vis,0,sizeof(vis));
            read(n); read(m);
            for (i=1;i<n;++i)
            {
                read(x); read(y); read(z);
                add(x,y,z); ru[y]++;
            }
            for (i=1;i<=n;++i)
            if (!ru[i]) { root=i; break; }
            dis[root]=0;
            DFS(root);
            for (i=1;i<=n;++i)
            father[i]=i;
            for (i=1;i<=m;++i)
            {
                read(a[i].x); read(a[i].y);
                qadd(a[i].x,a[i].y,i), qadd(a[i].y,a[i].x,i);
            }
            LCA(root);
            for (i=1;i<=m;++i)
            write(dis[a[i].x]+dis[a[i].y]-2*dis[a[i].fa]),putchar('
    ');
        }
        return 0;
    }
  • 相关阅读:
    navigateTo防止多次跳转
    vue中的绑定class和微信小程序中的绑定class的区别
    js同步和异步
    本地存储和vuex使用对比
    微信小程序页面跳转区别总结
    CAS-技术专区-认证服务器cas-server搭建
    CAS-技术专区-SSO配置完整案例(静态认证+数据库认证)
    SpringCloud-技术专区-实战案例-Zuul整合OAuth2.0认证服务
    OAuth2.0协议专区-SpringCloud安全-集成OAuth2实现身份认证和单点登录
    OAuth2.0协议专区-SpringCloud微服务实战-基于OAUTH2.0统一认证授权的微服务基础架构
  • 原文地址:https://www.cnblogs.com/cjjsb/p/8473911.html
Copyright © 2011-2022 走看看