zoukankan      html  css  js  c++  java
  • 1558:聚会 ybt

    1558:聚会 ybt 题解(看似很难,其实要是摸清了实质这就是个大水题)

    上题目

    1558:聚会


    时间限制: 1000 ms         内存限制: 524288 KB
    提交数: 82     通过数: 56

    【题目描述】

    原题来自:AHOI 2008

    Y

    岛风景美丽宜人,气候温和,物产丰富。Y 岛上有 N 个城市,有 N1 条城市间的道路连接着它们。每一条道路都连接某两个城市。幸运的是,小可可通过这些道路可以走遍 Y

    岛的所有城市。神奇的是,乘车经过每条道路所需要的费用都是一样的。

    小可可,小卡卡和小 YY

    经常想聚会,每次聚会,他们都会选择一个城市,使得三个人到达这个城市的总费用最小。

    由于他们计划中还会有很多次聚会,每次都选择一个地点是很烦人的事情,所以他们决定把这件事情交给你来完成。他们会提供给你地图以及若干次聚会前他们所处的位置,希望你为他们的每一次聚会选择一个合适的地点。

    【输入】

    第一行两个正整数,N

    M

    。分别表示城市个数和聚会次数;

    后面有 N1

    行,每行用两个正整数 AB 表示编号为 A 和编号为 B 的城市之间有一条路。城市的编号是从 1N

    的;

    再后面有 M

    行,每行用三个正整数表示一次聚会的情况:小可可所在的城市编号,小卡卡所在的城市编号以及小 YY

    所在的城市编号。

    【输出】

    一共有 M

    行,每行两个数 PC,用一个空格隔开。表示第 i 次聚会的地点选择在编号为 P 的城市,总共的费用是经过 C

    条道路所花费的费用。

    【输入样例】

    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

    【提示】

    数据范围与提示:

    40% 的数据中,1N,M2×103

    100% 的数据中,1N,M5×105

    乍一看这道题正常人的脑子里都会想到最短路 在不看这一节的标题的情况下

    但是这道题的本质却是找规律。。。。在纸上画一画就很容易想到

    我们分别找出这三个点的LCA,会发现三个LCA当中必有两个相同的点(可以数学证明但是我不会)

    而最终要去的那个点就是除了上述两点之外的第三个点

    #include<bits/stdc++.h>
    using namespace std;
    const int N=5e5+1;
    int n,m,tot;
    int next[N<<1],head[N<<1],f[N<<1][21],Dep[N<<1],to[N<<1];
    
    inline int read()
    {
        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;
    }
    
    inline void Add(int from,int pos)
    {
        next[++tot]=head[from];
        head[from]=tot;
        to[tot]=pos;
    }
    
    inline void Pre(int u,int fa)
    {
        Dep[u]=Dep[fa]+1;
        f[u][0]=fa;
        for(int i=1;i<=19;i++)
        f[u][i]=f[f[u][i-1]][i-1];
        for(int i=head[u];i;i=next[i])
        {
            if(to[i]==fa) continue;
            //dis[to[i]]=dis[u]+1;
            Pre(to[i],u);
        }
    }
    
    inline int LCA(int x,int y)
    {
        if(Dep[x]<Dep[y]) swap(x,y);
        for(int i=19;i>=0;i--)
        {
            if(Dep[f[x][i]]>=Dep[y]) x=f[x][i];
            if(x==y) return x;
        }
        for(int i=19;i>=0;i--)
        {
            if(f[x][i]!=f[y][i])
            {
                x=f[x][i];
                y=f[y][i];
            }
        }
        return f[x][0];
    }
    
    inline int Q(int x,int y)
    {
        return (Dep[x]+Dep[y]-2*Dep[LCA(x,y)]);
    }
    
    inline int query(int x,int y,int z,int end)
    {
        return (Q(x,end)+Q(y,end)+Q(z,end));
    }
    int main()
    {
        n=read();m=read();
        int x,y,z;
        int A,B,C; 
        for(int i=1;i<n;i++)
        {
            x=read();y=read();
            Add(x,y);
            Add(y,x);
        }
        Pre(1,1);
        for(int i=1;i<=m;i++)
        {
            x=read();y=read();z=read();
            A=LCA(x,y);
            B=LCA(x,z);
            C=LCA(y,z);
            if(A==B) printf("%d %d
    ",C,query(x,y,z,C));
            else if(A==C) printf("%d %d
    ",B,query(x,y,z,B));
            else printf("%d %d
    ",A,query(x,y,z,A));
        }
        return 0;
    }
    喵内喵内
  • 相关阅读:
    Google Map API使用详解(三)——Google Map基本常识(上)
    Google Map API使用详解(十)——使用JavaScript创建地图详解(上)
    sethc.exe
    taobao_java
    "void __cdecl operator delete[](void *)" (??_V@YAXPAX@Z) 已经在 LIBCMTD.lib(delete2.obj) 中定义 错误
    some Content
    变参 C++ 转帖
    阅读大型程序你得到什么
    一些模块
    a common jsp
  • 原文地址:https://www.cnblogs.com/smartljy/p/11352845.html
Copyright © 2011-2022 走看看