zoukankan      html  css  js  c++  java
  • bzoj 1832 lca

    1832: [AHOI2008]聚会

    Time Limit: 10 Sec  Memory Limit: 64 MB

    Description

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

    Input

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

    Output

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

    Sample Input

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

    Sample Output

    5 2
    2 5
    4 1
    6 0

    数据范围:
    100%的数据中,N<=500000,M<=500000。
    40%的数据中N<=2000,M<=2000。
    思路:求三点lca,取两点求lca再求另外一个点到lca的最小值
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<string>
    #include<queue>
    #include<algorithm>
    #include<stack>
    #include<cstring>
    #include<vector>
    #include<list>
    #include<set>
    #include<map>
    #define true ture
    #define false flase
    using namespace std;
    #define ll long long
    #define inf 0xfffffff
    int scan()
    {
        int res = 0 , ch ;
        while( !( ( ch = getchar() ) >= '0' && ch <= '9' ) )
        {
            if( ch == EOF )  return 1 << 30 ;
        }
        res = ch - '0' ;
        while( ( ch = getchar() ) >= '0' && ch <= '9' )
            res = res * 10 + ( ch - '0' ) ;
        return res ;
    }
    #define maxn 500010
    #define M 22
    struct is
    {
        int v,next;
    }edge[maxn*2];
    int deep[maxn],jiedge;
    int head[maxn];
    int fa[maxn][M];
    void add(int u,int v)
    {
        jiedge++;
        edge[jiedge].v=v;
        edge[jiedge].next=head[u];
        head[u]=jiedge;
    }
    void dfs(int u)
    {
        for(int i=head[u];i;i=edge[i].next)
        {
            int v=edge[i].v;
            if(!deep[v])
            {
                deep[v]=deep[u]+1;
                fa[v][0]=u;
                dfs(v);
            }
        }
    }
    void st(int n)
    {
        for(int j=1;j<M;j++)
        for(int i=1;i<=n;i++)
        fa[i][j]=fa[fa[i][j-1]][j-1];
    }
    int LCA(int u , int v)
    {
        if(deep[u] < deep[v]) swap(u , v) ;
        int d = deep[u] - deep[v] ;
        int i ;
        for(i = 0 ; i < M ; i ++)
        {
            if( (1 << i) & d )  // 注意此处,动手模拟一下,就会明白的
            {
                u = fa[u][i] ;
            }
        }
        if(u == v) return u ;
        for(i = M - 1 ; i >= 0 ; i --)
        {
            if(fa[u][i] != fa[v][i])
            {
                u = fa[u][i] ;
                v = fa[v][i] ;
            }
        }
        u = fa[u][0] ;
        return u ;
    }
    void init()
    {
        memset(head,0,sizeof(head));
        memset(fa,0,sizeof(fa));
        memset(deep,0,sizeof(deep));
        jiedge=0;
    }
    struct kk
    {
        int a,b;
    }a[4];
    kk ans(int x,int y,int z)
    {
        int ans=LCA(x,y);
        int road=abs(deep[x]-deep[ans])+abs(deep[y]-deep[ans]);
        int gg=LCA(ans,z);
        road+=abs(deep[z]-deep[gg])+abs(deep[gg]-deep[ans]);
        kk lll;
        lll.a=ans;
        lll.b=road;
        return lll;
    }
    int main()
    {
        int x,n;
        init();
        scanf("%d%d",&n,&x);
        for(int i=1;i<n;i++)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                add(u,v);add(v,u);
            }
            deep[1]=1;
            dfs(1);
            st(n);
            for(int i=0;i<x;i++)
            {
                scanf("%d%d%d",&a[0].a,&a[1].a,&a[2].a);
                kk minn;
                minn.b=inf;
                kk ji;
                ji=ans(a[0].a,a[1].a,a[2].a);
                if(ji.b<minn.b)
                minn=ji;
                ji=ans(a[2].a,a[0].a,a[1].a);
                if(ji.b<minn.b)
                minn=ji;
                ji=ans(a[2].a,a[1].a,a[0].a);
                if(ji.b<minn.b)
                minn=ji;
                printf("%d %d
    ",minn.a,minn.b);
            }
        return 0;
    }
    View Code
  • 相关阅读:
    javascript修改浏览器title方法 JS动态修改浏览器标题
    input type="checkbox" 选中传值,不选中传值的方法讲解
    关闭控制台的自动切换按钮
    mac切图
    charles
    apache
    超级经典的HTTP协议讲解
    一个很有趣的算法
    移动端网络判断
    移动端1px细线的处理
  • 原文地址:https://www.cnblogs.com/jhz033/p/5402305.html
Copyright © 2011-2022 走看看