zoukankan      html  css  js  c++  java
  • 洛谷 P4281 [AHOI2008]紧急集合 / 聚会(树剖,LCA)

    传送门


    解题思路

    题目很长,实际上就是给你一棵树,然后给你三个点,让你找到一个点,是这个点到三个点的距离和最短。

    很显然的是,这个点在这三个点简单路径的上,而这三条简单路径一定有且只有一个交汇点,这个交汇点就是答案。

    这就是为什么一定有一个交点,而且这个交点是其中两个点的LCA,且这个LCA是深度最深的LCA。

    因为如果取深度较浅的LCA,则a,b两点交汇后要一同走一段路程,花费两个人的金币,就不如让c多走一段距离了。

    而深度较浅的那个点,一定就是三个LCA r1,r2,r3 中与其他两个不相同的那个LCA。(r1==r2==r3的情况特判)。

    AC代码

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 using namespace std;
     5 const int maxn=500005;
     6 int n,m,fa[maxn],dep[maxn],son[maxn],p[maxn],tp[maxn],cnt,size[maxn];
     7 struct node{
     8     int v,next;
     9 }e[maxn*2];
    10 void insert(int u,int v){
    11     cnt++;
    12     e[cnt].v=v;
    13     e[cnt].next=p[u];
    14     p[u]=cnt;
    15 }
    16 void dfs1(int u,int dad,int deep){
    17     int maxsize=0;
    18     fa[u]=dad;
    19     dep[u]=deep;
    20     size[u]=1;
    21     for(int i=p[u];i!=-1;i=e[i].next){
    22         int v=e[i].v;
    23         if(v==dad) continue;
    24         dfs1(v,u,deep+1);
    25         size[u]+=size[v];
    26         if(size[v]>maxsize){
    27             son[u]=v;
    28             maxsize=size[v];
    29         }
    30     }
    31 }
    32 void dfs2(int u,int top){
    33     tp[u]=top;
    34     if(son[u]) dfs2(son[u],top);
    35     for(int i=p[u];i!=-1;i=e[i].next){
    36         int v=e[i].v;
    37         if(v==fa[u]||v==son[u]) continue;
    38         dfs2(v,v);
    39     }
    40 }
    41 int getrt(int x,int y){
    42     while(tp[x]!=tp[y]){
    43         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
    44         x=fa[tp[x]];
    45     }    
    46     return dep[x]>dep[y]?y:x; 
    47 }
    48 int main(){
    49     memset(p,-1,sizeof(p));
    50     cin>>n>>m;
    51     for(int i=1;i<n;i++){
    52         int u,v;
    53         scanf("%d%d",&u,&v);
    54         insert(u,v);
    55         insert(v,u);
    56     }
    57     dfs1(1,-1,1);
    58     dfs2(1,1);
    59     for(int i=1;i<=m;i++){
    60         int a,b,c;
    61         scanf("%d%d%d",&a,&b,&c);
    62         int r1=getrt(a,b);
    63         int r2=getrt(a,c);
    64         int r3=getrt(b,c);
    65         int ans=dep[a]+dep[b]+dep[c]-dep[r1]-dep[r2]-dep[r3];
    66         if(r1==r2) printf("%d %d
    ",r3,ans);
    67         else if(r1==r3) printf("%d %d
    ",r2,ans);
    68         else if(r2==r3) printf("%d %d
    ",r1,ans);
    69     }
    70     return 0;
    71 } 

    //AHOI 2008

  • 相关阅读:
    web端常见兼容性问题整理
    浏览器初始化样式
    html5特效库
    csshack
    进程与线程,并发、并行、异步、多线程
    js复制粘贴事件
    dom range相关
    vue和react在使用上的对比
    ListView往TreView里面拖拽
    ListView添加项目带序列
  • 原文地址:https://www.cnblogs.com/yinyuqin/p/13709511.html
Copyright © 2011-2022 走看看