HDU - 6115 Factory (LCA 倍增)

Posted ljwcarrot

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 6115 Factory (LCA 倍增)相关的知识,希望对你有一定的参考价值。

题目传送门:HDU - 6115  Factory

题目大意:

(中文题,简单解答下题意)

存在N个城市和M个百度的子公司,N个城市间有N-1条道路连接(一颗树),每个子公司都有办公室,办公室分布在各个城市,现在提问,两个子公司间的最小距离。

分析:

枚举提问的两个子公司的办公室间的距离,求出最短距离即可:

例如:子公司company1办公室在城市 1 2 3     子公司company2的办公室在城市5 6 ,若求company1,company2的最短距离,即枚举(1,5)、(1,6)、(2,5)、(2,6)、(3,5)、(3,6)的距离,求出最小值即可。

求距离:设求城市a,b的距离,先用倍增求出lca(a,b),然后dis=dis[a]+dis[b]-2*dis[lca(a,b)]得到距离;

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;
const int MAX=100009;
const int M=20;
int t,n,m,a,b,val,num,q;
int head[MAX],cnt=0;
int up[MAX][M];
int deep[MAX];
int dis[MAX];
vector<int>comp[MAX];
struct Edge{                                //存树 
    int next,to,val;
}edge[MAX*2];
inline void add(int u,int v,int w)
{
    edge[cnt].to=v;
    edge[cnt].val=w;
    edge[cnt].next=head[u];
    head[u]=cnt++;
}
void dfs(int u)                                    //dfs遍历求出深度和距离 
{
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        int to=edge[i].to;
        if(to==up[u][0])continue;
        deep[to]=deep[u]+1;
        up[to][0]=u;
        dis[to]=dis[u]+edge[i].val;
        dfs(to);
    }
}
void init()                                         
{
    for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i<=n;i++)
            up[i][j]=up[up[i][j-1]][j-1];
}
int lca(int a,int b)
{
    if(deep[a]<deep[b])swap(a,b);
    int d=deep[a]-deep[b];
    for(int i=0;i<M;i++)
        if((1<<i)&d)
            a=up[a][i];
            
    if(a==b)return a;
    for(int i=M-1;i>=0;i--)
    {
        if(up[a][i]!=up[b][i])
        {
            a=up[a][i];b=up[b][i];
        }
    }
    return up[a][0];
}
int main()
{
    scanf("%d",&t);
    while(t--)
    {
        memset(head,-1,sizeof(head));cnt=0;                    //初始化 
        memset(up,0,sizeof(up));
        memset(deep,0,sizeof(deep));
        memset(dis,0,sizeof(dis));
        for(int i=0;i<MAX;i++)
            comp[i].clear();
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&a,&b,&val);
            add(a,b,val);
            add(b,a,val);
        }
        dfs(1); 
        init();
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&num);
            for(int j=0;j<num;j++)                        //vector存子公司的办公室所在城市 
            {
                scanf("%d",&a);
                comp[i].push_back(a);
            }
        }
        scanf("%d",&q);
        int l,res,min;
        for(int i=0;i<q;i++)
        {    
            min=0x3f3f3f3f;
            scanf("%d%d",&a,&b);
            for(int k=0;k<comp[a].size();k++)    
            {
                for(int q=0;q<comp[b].size();q++)                        //枚举 
                {    
                     l=lca(comp[a][k],comp[b][q]);
                     res=dis[comp[a][k]]+dis[comp[b][q]]-2*dis[l];
                     if(res<min)
                     {
                         min=res;
                     }
                    
                }         
            }
            printf("%d
",min);
        }
    }
    return 0;
}

 

以上是关于HDU - 6115 Factory (LCA 倍增)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 1671 Phone List

HDU5266[XSYOJ2315]LCA_LCA_线段树

HDU 2586 LCA

hdu 2586 How far away ?倍增LCA

HDU 2586 How far away ?(LCA在线算法实现)

hdu 6031 Innumerable Ancestors (虚树 lca)