zoukankan      html  css  js  c++  java
  • 聚会

    题目描述

    Y岛风景美丽宜人,气候温和,物产丰富。Y岛上有N个城市,有N-1条城市间的道路连接着它们。每一条道路都连接某两个城市。幸运的是,小可可通过这些道路可以走遍Y岛的所有城市。神奇的是,乘车经过每条道路所需要的费用都是一样的。小可可,小卡卡和小YY经常想聚会,每次聚会,他们都会选择一个城市,使得3个人到达这个城市的总费用最小。 由于他们计划中还会有很多次聚会,每次都选择一个地点是很烦人的事情,所以他们决定把这件事情交给你来完成。他们会提供给你地图以及若干次聚会前他们所处的位置,希望你为他们的每一次聚会选择一个合适的地点。

    输入

    第一行两个正整数,N和M。分别表示城市个数和聚会次数。后面有N-1行,每行用两个正整数A和B表示编号为A和编号为B的城市之间有一条路。城市的编号是从1到N的。再后面有M行,每行用三个正整数表示一次聚会的情况:小可可所在的城市编号,小卡卡所在的城市编号以及小YY所在的城市编号。

    输出

    一共有M行,每行两个数Pos和Cost,用一个空格隔开。表示第i次聚会的地点选择在编号为Pos的城市,总共的费用是经过Cost条道路所花费的费用。

    样例输入

    6 4
    1 2
    2 3
    2 4
    4 5
    5 6
    4 5 6
    6 3 1
    2 4 4
    6 6 6
    

    样例输出

    5 2
    2 5
    4 1
    6 0
    

    提示

    100%的数据中,N<=500000,M<=500000。
    40%的数据中N<=2000,M<=2000。

    LCA
    最近的点,一定是在两个点的LCA处,枚举一下,取最小值就可以啦~
    #include <bits/stdc++.h>
    #define maxn 500055
    using namespace std;
    struct Edge
    {
        int v,next;
    };
    int n,m,t;
    struct Map
    {
        int head[maxn];
        Edge edge[maxn<<1];
        int cnt;
        int fa[maxn][25];
        bool vis[maxn];
        int depth[maxn];
        inline void init()
        {
            memset(head,-1,sizeof(head));
            cnt=0;
        }
        inline void addedge(int u,int v)
        {
            edge[cnt].v=v;
            edge[cnt].next=head[u];
            head[u]=cnt++;
        }
        inline void bfs()
        {
            queue<int> q;
            memset(vis,false,sizeof(vis));
            memset(depth,0,sizeof(depth));
            vis[1]=true;
            q.push(1);
            depth[1]=1;
            while(!q.empty())
            {
                int u=q.front();
                q.pop();
                for(int i=head[u]; i!=-1; i=edge[i].next)
                {
                    int v=edge[i].v;
                    if(!vis[v])
                    {
                        vis[v]=true;
                        depth[v]=depth[u]+1;
                        fa[v][0]=u;
                        for(int j=1; j<=t; j++)
                        {
                            fa[v][j]=fa[fa[v][j-1]][j-1];
                        }
                        q.push(v);
                    }
                }
            }
        }
        inline int lca(int x,int y)
        {
            if(depth[x]>depth[y]) swap(x,y);
            for(int i=t;i>=0;--i)
            {
                if(depth[fa[y][i]]>=depth[x]) y=fa[y][i];
            }
            if(x==y) return x;
            for(int i=t;i>=0;--i)
            {
                if(fa[x][i]!=fa[y][i])
                {
                    x=fa[x][i];
                    y=fa[y][i];
                }
            }
            return fa[x][0];
        }
        inline int reads()
    {
        int x=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x*f;
    }
        void read()
        {
            scanf("%d%d",&n,&m);
            init();
            t=(int)(log(n)/log(2))+1;
            for(int i=1; i<=n-1; ++i)
            {
                int u,v;
                u=reads();
                v=reads();
                addedge(u,v);
                addedge(v,u);
            }
            bfs();
            for(int i=1;i<=m;++i)
            {
            int x,y,z;
            x=reads();
            y=reads();
            z=reads();
            ask(x,y,z);
            }
        }
        inline void ask(int x,int y,int z)
        {
            int num1=lca(x,y);
            int num2=lca(x,z);
            int num3=lca(y,z);
            int num4=lca(z,num1);
            int ans=depth[x]+depth[y]+depth[z]-3*depth[num4];
            int pos=num4;
            int temp=depth[x]+depth[y]-2*depth[num1]+depth[z]+depth[num1]-2*depth[num4];
            if(ans>temp)
            {
                ans=temp;
                pos=num1;
            }
            temp=depth[x]+depth[z]-2*depth[num2]+depth[y]+depth[num2]-2*depth[num4];
            if(ans>temp)
            {
                ans=temp;
                pos=num2;
            }
            temp=depth[y]+depth[z]-2*depth[num3]+depth[x]+depth[num3]-2*depth[num4];
            if(ans>temp)
            {
                ans=temp;
                pos=num3;
            }
            printf("%d %d
    ",pos,ans);
        }
     
    } Mp;
    int main()
    {
        Mp.read();
        //printf("%d
    ",Mp.lca(2,3));
        return 0;
    }
    

      

  • 相关阅读:
    POJ 1149 PIGS(Dinic最大流)
    HDU 4514 湫湫系列故事——设计风景线(并查集+树形DP)
    [kuangbin带你飞]专题十一 网络流个人题解(L题留坑)
    BZOJ 3931 网络吞吐量(最短路+拆点最大流)
    学习RMQ-ST表
    `这个符号在mysql中的作用
    用一条mysql语句插入多条数据
    Leetcode 257 Binary Tree Paths 二叉树 DFS
    Leetcode 203 Remove Linked List Elements 链表
    Leetcode 38 Count and Say 传说中的递推
  • 原文地址:https://www.cnblogs.com/zyf3855923/p/9784081.html
Copyright © 2011-2022 走看看