zoukankan      html  css  js  c++  java
  • HDU-2586,LCA模板题

                                  HDU-2586   How far away ?

    题目大意:给你n个节点组成的树,树的每条边上都有一定的权值,问你树上两点之间的

    距离是多少

    具体思路:此题是在学习tarjan中找到的一道题,由于题目给出的是一个树,可以联想到

    子节点与根节点之间的关系,我们可以通过dfs求出子节点与根节点之间的距离,对于树中

    任意的两个子节点到根节点中,总有重合的部分,然而这部分是不用计算在内的。因此我们可以求出

    距离两个子节点比较近的节点再减去这个节点到根节点的距离就是了,因此我们要求两个点的最近公共祖先

    LCA讲解:https://www.cnblogs.com/JVxie/p/4854719.html

    题目可以有两种解法,第一种是通过倍增求LCA在线处理,第二种是dfs离线处理

     

    #include<iostream>//第一种
    #include<vector>
    #include<algorithm>
    #pragma comment(linker, "/STACK:1024000000,1024000000")
    using namespace std;
    const int maxn=400004;
    struct node
    {
        int to,w;
        node(int a=0,int b=0){
            to=a;
            w=b;
        }
    };
    vector<node>q[maxn];
    int f[maxn],p[maxn][20],deep[maxn],dis[maxn],n;
    void dfs(int u,int pre,int t)
    {
        deep[u]=t;
        f[u]=pre;
        for(int i=0;i<q[u].size();i++)
        {
              int v=q[u][i].to;
              if(v!=pre)
              {
                  dis[v]=dis[u]+q[u][i].w;
                  dfs(v,u,t+1);
              }    
        }    
    } 
    //int a[100005]; 
    void init()
    {
        int i,j;
        for(j=0;(1<<j)<=n;j++)
        {
            for( i=1;i<=n;i++)
            {
                p[i][j]=-1;
            }
        }
        for(int i=1;i<=n;i++) p[i][0]=f[i];
        for(j=1;(1<<j)<=n;j++)
        {
            for (i=1;i<=n;i++)
            {
               if(p[i][j-1]!=-1) p[i][j]=p[p[i][j-1]][j-1];
             }
        }    
    }
    int lca(int a,int b)
    {
        int i,j;
        if(deep[a]<deep[b]) swap(a,b);
        for(i=0;(1<<i)<=deep[a];i++)
        {
            
        }
        i--;
        for(j=i;j>=0;j--)
        {
            if(deep[a]-(1<<j)>=deep[b])
            a=p[a][j];
        }
        if(a==b)return a;
        for(j=i;j>=0;j--)
        {
            if(p[a][j]!=-1&&p[a][j]!=p[b][j])
            {
                a=p[a][j];
                b=p[b][j];
            }
        }
        return f[a];
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int m;
            cin>>n>>m;
            for(int i=1;i<=n;i++) q[i].clear();
            for(int i=1;i<n;i++)
            {
                int a,b,c;
                cin>>a>>b>>c;
                q[a].push_back(node(b,c));
                q[b].push_back(node(a,c));
            }
            dis[1]=0;
            dfs(1,-1,0);
            init();
            while(m--)
            {
                int a,b;
                cin>>a>>b;
                int ans=dis[a]+dis[b]-2*dis[lca(a,b)];
                cout<<ans<<endl;
            }
        }
        return 0;
    }

     

    #pragma comment(linker, "/STACK:1024000000,1024000000")
    #include<iostream>//第二种
    #include<vector>
    #include<algorithm>
    using namespace std;
    const int maxn=4e5+4;
    struct node
    {
        int to,w;
        node(int a=0,int b=0)
        {
            to=a;
            w=b;
        }
    };
    vector<node>q[maxn];
    vector<node>e[maxn];
    int f[maxn],dis[maxn],vis[maxn],n,ans[maxn];
    int finds(int x)
    {
        if(x==f[x]) return x;
        else return  f[x]=finds(f[x]);
    }
    void lca(int u)
    {
            vis[u]=1;
        for(int i=0;i<q[u].size();i++)
        {
            int v=q[u][i].to;
            if(vis[v]) continue;
            //vis[v]=1;
            dis[v]=dis[u]+q[u][i].w;
            lca(v);
            f[v]=u;
            for(int j=0;j<e[v].size();j++)
            {
                int c=e[v][j].to;
                if(vis[c]&&ans[e[v][j].w]==-1)
                {
                    if(v==c) ans[e[v][j].w]=0;
                    else ans[e[v][j].w]=dis[c]+dis[v]-2*dis[finds(c)];
                }
            }
        }
        
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--)
        {
            int m;
            cin>>n>>m;
            for(int i=1;i<=n;i++)
            {
                q[i].clear();
                e[i].clear();
                vis[i]=0;
                f[i]=i;
                ans[i]=-1;
            }
            for(int i=1;i<n;i++)
            {
                int a,b,c;
                cin>>a>>b>>c;
                q[a].push_back(node(b,c));
                q[b].push_back(node(a,c));
            }
            for(int i=1;i<=m;i++){
                int a,b;
                cin>>a>>b;
                e[a].push_back(node(b,i));
                e[b].push_back(node(a,i));
            }
        
            dis[1]=0;
            lca(1);
            for(int i=1;i<=m;i++) cout<<ans[i]<<endl;
            //cout<<endl;
        }
    
    }

    以上解题思路来源于:https://blog.csdn.net/a601025382s/article/details/10615039

     

  • 相关阅读:
    MySQL优化实例
    MySQL优化步骤和my.cnf优化配置
    linux高负载下mysql数据库彻底优化
    MySQL配置文件my.cnf详解
    CentOS Linux下MySQL 5.1.x的安装、优化和安全配置
    Apache 配置文件详解
    [LeetCode] Number of Boomerangs
    [LeetCode] Binary Watch
    [LeetCode] Reverse Linked List
    [LeetCode] Maximum Product of Three Numbers
  • 原文地址:https://www.cnblogs.com/tombraider-shadow/p/11240133.html
Copyright © 2011-2022 走看看