zoukankan      html  css  js  c++  java
  • 【洛谷P3884 [JLOI2009]】二叉树问题

    题目描述

    如下图所示的一棵二叉树的深度、宽度及结点间距离分别为:

    深度:4 宽度:4(同一层最多结点个数)

    结点间距离: ⑧→⑥为8 (3×2+2=8)

    ⑥→⑦为3 (1×2+1=3)

    注:结点间距离的定义:由结点向根方向(上行方向)时的边数×2,

    与由根向叶结点方向(下行方向)时的边数之和。

     

    输入输出格式

    输入格式:

    输入文件第一行为一个整数n(1≤n≤100),表示二叉树结点个数。接下来的n-1行,表示从结点x到结点y(约定根结点为1),最后一行两个整数u、v,表示求从结点u到结点v的距离。

    输出格式:

    三个数,每个数占一行,依次表示给定二叉树的深度、宽度及结点u到结点v间距离。

    输入输出样例

    输入样例#1

    10                               

    1 2                           

    1 3                            

    2 4

    2 5

    3 6

    3 7

    5 8

    5 9

    6 10

    8 6

    输出样例#1

    4

    4

    8

    算法:

    最近公共祖先(LCA)倍增

     

    分析:

    看题看了很久都没看懂,后来才发现这个是一个几乎lca的模板问题,只用把路径处理一下就好了,这里采用倍增的算法。

     

    上代码:

     

     1 #include<cstdio>
     2 #define max(a,b) a>b?a:b
     3 #define swap(a,b) a^=b^=a^=b
     4 #define maxn 110
     5 using namespace std;
     6 
     7 int n,m,s,tot,head[maxn],deep[maxn],p[maxn][20],md,t[10],ans;
     8 struct node
     9 {
    10     int nxt,to;
    11 }edge[maxn<<1];
    12 
    13 int read()
    14 {
    15     int x=0,f=1;
    16     char c=getchar();
    17     while (c<48||c>57)
    18         f=c=='-'?-1:1,c=getchar();
    19     while (c>=48&&c<=57)
    20         x=(x<<1)+(x<<3)+(c^48),c=getchar();
    21     return x*f;
    22 }
    23 
    24 void add(int a,int b)
    25 {
    26     edge[++tot]=(node){head[a],b};
    27     head[a]=tot;
    28     edge[++tot]=(node){head[b],a};
    29     head[b]=tot;
    30 }
    31 
    32 void init()
    33 {
    34     for (int j=1;(1<<j)<=n;j++)
    35         for (int i=1;i<=n;i++)
    36             if (p[i][j-1])
    37                 p[i][j]=p[p[i][j-1]][j-1];
    38 }
    39 
    40 int dfs(int u)
    41 {
    42     for (int i=head[u];i;i=edge[i].nxt)
    43         if (!deep[edge[i].to])
    44         {
    45             deep[edge[i].to]=deep[u]+1;
    46             p[edge[i].to][0]=u;
    47             dfs(edge[i].to);
    48         }
    49 }
    50 
    51 int LCA(int a,int b)
    52 {
    53     if (deep[a]<deep[b])
    54         swap(a,b);
    55     int i,j;
    56     for (i=0;(1<<i)<=deep[a];i++);
    57     i--;
    58     for (j=i;j>=0;j--)
    59         if (deep[b]<=deep[a]-(1<<j))
    60             a=p[a][j];
    61     if (a==b)
    62         return a;
    63     for (j=i;j>=0;j--)
    64         if (p[a][j]!=p[b][j]&&deep[p[a][j]]>=1)
    65         {
    66             a=p[a][j];
    67             b=p[b][j];
    68         }
    69     return p[a][0];
    70 }
    71 
    72 int main()
    73 {
    74     int i,j,k,u,v;
    75     n=read();
    76     for (i=1;i<=n-1;i++)
    77         add(read(),read());
    78     u=read(),v=read();
    79     deep[1]=1;
    80     dfs(1);
    81     init();
    82     for (i=1;i<=n;i++)
    83         md=max(md,deep[i]),t[deep[i]]++;
    84     for (i=1;i<=9;i++)
    85         t[0]=max(t[0],t[i]);
    86     k=LCA(u,v);
    87     ans=(deep[u]-deep[k])*2+deep[v]-deep[k];
    88     printf("%d
    %d
    %d",md,t[0],ans);
    89     return 0;
    90 }
  • 相关阅读:
    第七周-学习进度条
    《梦断代码》阅读笔记01
    第六周-学习进度条
    构建之法阅读笔记03
    结对项目开发(石家庄地铁乘车系统)
    第五周-学习进度条
    第四周-学习进度条
    HDU--1272 小希的迷宫(并查集判环与联通)
    HDU--1856 More is better(简单带权并查集)
    HDU--3635 带权并查集
  • 原文地址:https://www.cnblogs.com/Ronald-MOK1426/p/8999233.html
Copyright © 2011-2022 走看看