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

    题解思路:

    原本的打算是先建立一棵树,再进行dfs。但对于此题,已经知道根节点始终是1且各节点连接信息表现出来的情况下,可以直接利用邻接矩阵+dfs从根节点搜,保存各节点的深度信息即可。

           具体步骤如下:
           1.先使用邻接矩阵(即二维数组)储存各节点长度关系,如a[i][j]储存第i和第j个结点的距离,若两节点不连接,则设置为0。

           2.首先,从根节点(1)开始往下搜,用dfs遍历所有的结点,在遍历的同时用depth数组储存各节点的深度,如根节点1的深度为1,每访问到一个节点就保存深度信息。

           3.有了结点信息后,进行排序求出最大深度。另外,通过统计相同的深度的节点数量即可确定树的最大宽度。

           4.接下来,开始对起始要搜索的点dfs,当碰见一个节点,进行深度比较,若深度大于该节点则路程加2,若小于该节点则路程加1,知道遇到终止点。、

    代码

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 
     6 //原本的打算是先建立一棵树,再进行dfs 
     7 //但对于此题,已经知道根节点始终是1且各节点连接信息表现出来的情况下,可以直接利用邻接矩阵+dfs从根节点搜,保存各节点的深度信息即可 
     8 #define INF 999999999
     9 int depth[101];    //记录各节点的深度信息 
    10 int broad[100];    //记录宽度(dfs后记录) 
    11 int map[101][101]={0};        //邻接矩阵,0代表无连接,1代表连接 
    12 int n=0;
    13 int flag[101]={0};        //存储各节点是否被访问的信息 
    14 int u=0,v=0;        //起始和目标 
    15 int minsum=INF;
    16 
    17 bool cmp(int a,int b){
    18     return a>b;
    19 }
    20 void dfs(int cur,int dep){
    21     flag[cur]=1;
    22     depth[cur]=dep;
    23 //    cout<<"cur:"<<cur<<" depth:"<<depth[cur]<<endl;
    24     
    25     for(int i=1;i<=n;i++){
    26         if(flag[i]==1)    continue;        //防止来回搜死循环 
    27         if(map[cur][i]!=0){
    28             dfs(i,dep+1);
    29         }
    30         flag[i]=0;    //回溯 
    31     }
    32     return ; 
    33 }
    34 void dfs1(int cur,int sum){        //cur是结点编号,sum为当前距离 
    35 //    cout<<"cur:"<<cur<<" sum:"<<sum<<endl;
    36     flag[cur]=1;
    37     if(sum>=minsum){
    38         return ;        //剪枝 
    39     }
    40     if(cur==v){
    41         if(sum<minsum){
    42             minsum=sum;
    43         } 
    44         return;        //找到并返回,更新minsum 
    45     }
    46     
    47     for(int i=1;i<=n;i++){
    48         if(flag[i]==1)    continue;
    49         if(map[cur][i]!=0){
    50             if(depth[i]>depth[cur]){
    51                 dfs1(i,sum+1);        //向下搜 
    52             }else if(depth[i]<depth[cur]){
    53                 dfs1(i,sum+2);        //向上搜 
    54             }
    55         }
    56         flag[i]=0;    //回溯 
    57     }
    58     
    59     return;     
    60 }
    61 int main(){
    62     cin>>n;
    63     for(int i=1;i<=n-1;i++){
    64         int m,k;
    65         cin>>m>>k;
    66         map[m][k]=map[k][m]=1;
    67     }
    68     cin>>u>>v;
    69     
    70     dfs(1,1);
    71     int maxdepth=0;        //最大深度 
    72     int maxbroad=0;        //最大宽度 
    73     for(int i=1;i<=n;i++){
    74         if(depth[i]>maxdepth){
    75             maxdepth=depth[i];
    76         }
    77         broad[depth[i]]++;        //同一深度的结点数量累加 
    78     }
    79     sort(broad,broad+n,cmp);
    80     maxbroad=broad[0];
    81     
    82     //上述进行完树的深度和宽度查询后,下面开始距离搜索
    83     memset(flag,0,sizeof(flag));
    84     dfs1(u,0); 
    85     cout<<maxdepth<<endl<<maxbroad<<endl<<minsum;
    86     return 0;
    87 }
  • 相关阅读:
    20145220&20145209&20145309信息安全系统设计基础实验报告
    20145209 《信息安全系统设计基础》第8周学习总结
    R574
    gym102219
    102222F
    luogu 1337
    luogu 2503 & bzoj 2428
    18 BJ J
    poj 1981
    101992 I
  • 原文地址:https://www.cnblogs.com/xwh-blogs/p/12579957.html
Copyright © 2011-2022 走看看