zoukankan      html  css  js  c++  java
  • hdu2586How far away ?(LCA LCATarjan离线)

    题目链接acm.hdu.edu.cn/showproblem.php?pid=2586

    题目大意:有n个点,同n-1条带有权值的双向边相连,有m个询问,每个询问包含两个数x,y,求x与y的最短距离。

    例:

    Sample Input
    2
    3 2
    1 2 10
    3 1 15
    1 2
    2 3
     
    2 2
    1 2 100
    1 2
    2 1
    Sample Output
    10
    25
    100
    100
     
    解题思路:因为n个节点,含有n-1条边,我们可以把它看成一颗树,然后我们把1号节点看成这颗树的根节点,这样我们计算任意两个点x,y的最短距离就可以简单表示为dis[x]+dis[y]-2*dis[lca(x,y)](其中dis[i]表示节点i到根节点的距离,lca(x,y)表示x,y的最近公共祖先)。
    如果不会Tarjan离线算法可以看这个博客,http://www.cnblogs.com/JVxie/p/4854719.html,非常简单易懂。
    直接用Tarjan离线算法模板便可求出答案。
     
    附上代码:
    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<cstring>
    using namespace std;
    #define maxn 400005
    struct node{
        int x,y;
    };
    vector<node> edge[maxn],que[maxn];
    int ans[maxn],dis[maxn],par[maxn],vis[maxn];
    //ans[i]表示第i次询问的答案,dis[i]表示i号节点与根节点的距离
    //par[i]表示i号节点的父亲节点 
    int n,m;
    
    void init()
    {
        for(int i=1;i<=n;i++)
        {
            edge[i].clear();
            que[i].clear();
            par[i]=i;
            ans[i]=0;
            dis[i]=0;
            vis[i]=0;
        }
    }
    int find(int x)
    {
        if(x==par[x])
            return x;
        else
            return par[x]=find(par[x]);
    }
    void unite(int x,int y)
    {
        int fatherx=find(x),fathery=find(y);
        if(fatherx!=fathery)
            par[fathery]=fatherx;
    }
    void TarjanLCA(int x)
    {
        vis[x]=1;
        for(int i=0;i<edge[x].size();i++)
        {
            int v=edge[x][i].x;
            if(!vis[v])
            {
                dis[v]=dis[x]+edge[x][i].y;
                TarjanLCA(v);
                unite(x,v);
            }
        }
        for(int i=0;i<que[x].size();i++)
        {
            int v=que[x][i].x;
            if(vis[v])
                ans[que[x][i].y]=dis[x]+dis[v]-2*dis[find(v)];
        }
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            init();
            for(int i=1;i<n;i++)
            {
                int u,v,w;
                scanf("%d%d%d",&u,&v,&w);
                edge[u].push_back({v,w});
                edge[v].push_back({u,w});
            }
            for(int i=1;i<=m;i++)
            {
                int x,y;
                scanf("%d%d",&x,&y);
                que[x].push_back({y,i});//i表示第几次询问,便于输出 
                que[y].push_back({x,i});
            }
            TarjanLCA(1);
            for(int i=1;i<=m;i++)
                printf("%d
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    glog的编译和使用
    FFMPEG+SDL实现视频播放器
    SDL2学习(二):常用枚举值和函数
    SDL2学习(一): 显示一张图片
    2. chromium开发工具--gclient
    C# 获取时间大全
    用jquery-table2excel,进行导出excel
    SQL Server FOR XML PATH 和 STUFF函数的用法
    关于My Sql update语句不能用子查询的解决办法
    echarts呈现数据表图形
  • 原文地址:https://www.cnblogs.com/zjl192628928/p/9723324.html
Copyright © 2011-2022 走看看