zoukankan      html  css  js  c++  java
  • TTTTTTTTTTTTTTTTT HDU 2586 How far away LCA的离线算法 Tarjan

    链接:

    How far away ?

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 11204    Accepted Submission(s): 4079


    Problem Description
    There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B"? Usually it hard to answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can't visit a place twice) between every two houses. Yout task is to answer all these curious people.
     
    Input
    First line is a single integer T(T<=10), indicating the number of test cases.
      For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.
      Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.
     
    Output
    For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.
     
    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个房子用n-1条路连接起来,接下了有m次询问,每次询问两个房子a,b之间的距离是多少。
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <cmath>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <map>
    #include <algorithm>
    #include <set>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long Ull;
    #define MM(a,b) memset(a,b,sizeof(a));
    const double eps = 1e-10;
    const int  inf =0x7f7f7f7f;
    const double pi=acos(-1);
    const int maxn=40000;
    
    struct Edge{
        int to,w;
        Edge(int a,int b):to(a),w(b){};
        Edge(){};
    }e[maxn+10];
    
    struct node{
       int to,id;
    };
    
    vector<Edge> G[maxn+10];
    vector<node> mp[maxn+10];
    int vis[maxn+10],query[maxn+10][4],par[maxn+10],dis[maxn+10];
    
    int findr(int u)
    {
        if(par[u]!=u)
            par[u]=findr(par[u]);
        return par[u];
    }
    
    void unite(int u,int v)
    {
        int ru=findr(u);
        int rv=findr(v);
        if(ru!=rv) par[rv]=ru;
    }
    
    void tarjan(int u,int val)
    {
        vis[u]=1;
        dis[u]=val;
    
        for(int i=0;i<mp[u].size();i++)
        {
            int v=mp[u][i].to;
            int id=mp[u][i].id;
            if(vis[v])
                query[id][2]=findr(v);
        }
    
        for(int i=0;i<G[u].size();i++)
        {
            int v=G[u][i].to;
            if(vis[v]) continue;
            tarjan(v,val+G[u][i].w);
            unite(u,v);
        }
    
    }
    
    int main()
    {
        int cas,n,op,u,v,w;
        scanf("%d",&cas);
        while(cas--)
        {
            scanf("%d %d",&n,&op);
    
            for(int i=1;i<=n;i++)
            {
                G[i].clear();
                mp[i].clear();
                vis[i]=0;
                par[i]=i;
            }
    
            for(int i=1;i<=n-1;i++)
            {
                scanf("%d %d %d",&u,&v,&w);
                G[u].push_back(Edge(v,w));
                G[v].push_back(Edge(u,w));
            }
    
            for(int i=1;i<=op;i++)
            {
                scanf("%d %d",&u,&v);
                query[i][0]=u;
                query[i][1]=v;
                mp[u].push_back((node){v,i});
                mp[v].push_back((node){u,i});
            }
    
            tarjan(1,0);
    
            for(int i=1;i<=op;i++)
            {
                int u=query[i][0];
                int v=query[i][1];
                int r=query[i][2];
                printf("%d
    ",dis[u]+dis[v]-2*dis[r]);
            }
        }
        return 0;
    }

    分析:用的lca

    1.因为有n-1条边,任意两点之间可达,那么就是一棵树;

    2,假设当前是询问u和v两个点,他们的LCA是r,dis[]数组代表从根到点的距离,那么u和v两点之间的距离就是dis[u]+dis[v]-2*dis[r];所以只需要用Tarjan求一求询问的点对的LCA并且记录一下每个点到根(随便哪个点做根都可以)的距离就可以了

  • 相关阅读:
    什么是ORM
    ORM优缺点
    Azure 中快速搭建 FTPS 服务
    连接到 Azure 上的 SQL Server 虚拟机(经典部署)
    在 Azure 虚拟机中配置 Always On 可用性组(经典)
    SQL Server 2014 虚拟机的自动备份 (Resource Manager)
    Azure 虚拟机上的 SQL Server 常见问题
    排查在 Azure 中新建 Windows 虚拟机时遇到的经典部署问题
    上传通用化 VHD 并使用它在 Azure 中创建新 VM
    排查在 Azure 中新建 Windows VM 时遇到的部署问题
  • 原文地址:https://www.cnblogs.com/smilesundream/p/5455020.html
Copyright © 2011-2022 走看看