• HDU


    题目传送门: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;
    }
  • 相关阅读:
    mysql
    Spring MVC
    springSecurity
    导出Excel报表
    Redis集群搭建
    Oracle 分析数据库表行长度的统计信息 使用聚簇的步骤
    Dbms.job 学习
    oracel 学习系列
    Oracle 工具类 Sql 分析索引的 碎片率
    oracl
  • 原文地址:https://www.cnblogs.com/LjwCarrot/p/9689750.html
Copyright © 2020-2023  润新知