二叉树问题(洛谷3884)

一.题目描述

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

- 深度:4
- 宽度:4
- 结点 8 和 6 之间的距离:8
- 结点 7 和 6 之间的距离:3

其中宽度表示二叉树上同一层最多的结点个数,节点 u, v 之间的距离表示从 u 到 v 的最短有向路径上向根节点的边数的两倍加上向叶节点的边数。

给定一颗以 1 号结点为根的二叉树,请求出其深度、宽度和两个指定节点 x, y之间的距离。

## 输入格式

第一行是一个整数,表示树的结点个数 n。  
接下来 n - 1行,每行两个整数 u, v,表示树上存在一条连接 u, v 的边。  
最后一行有两个整数 x, y,表示求 x, y 之间的距离。

## 输出格式

输出三行,每行一个整数,依次表示二叉树的深度、宽度和 x, y 之间的距离。

## 样例 #1

### 样例输入 #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

## 提示

对于全部的测试点,保证1≤u,v,x,y≤n≤100且给出的是一棵树。

二.解题思路

将本题分为三个模块  1.求最大深度 2.求最大宽度 3.求节点距离

        模块①同时求最大深度和最大宽度(利用dfs)

        首先构造二叉树

        int q1, w;//分别为父节点,子节点
for (int i = 1; i < n; i++)
{
    cin >> q1 >> w;
    if (!a[q1].left)a[q1].left = w;//存左子节点
    else a[q1].right = w;//若左子存在元素,则放右子
    a[w].fath = q1;//存放子节点的父节点
}

套用上节dfs模版

a[1].steep = 1;//初始化步数。

调用dfs函数,进行深度搜索

void dfs(int t)
{
    if (b[t])return;
    b[t] = 1;
    int le = a[t].left, ri = a[t].right, st = a[t].steep;
    de = max(de, st);
    wide[st]++;//对每个深度进行累加(如节点4,5,6和7,深度都为3,即深度为3的有4个)
    if (le)
    {
        a[le].steep = st + 1;//子节点深度等于父节点+1
        dfs(le);//子节点遍历
    }
    if (ri)
    {
        a[ri].steep = st + 1;
        dfs(ri);
    }
}

模块②利用bfs求距离

需要一个结构体存放节点位置,和距离

typedef struct poin {
    int pot, str;
}tr;

定义一个该类型的队列queue<tr> q;

套用bfs模版:

memset(b, -1, sizeof(b));//遍历过的标记

tr sa = {x,0};//初始位置和距离
b[x] = 1;//标记初始位置
q.push(sa);

while (!q.empty())
{
    sa = q.front();
    q.pop();
    if (sa.pot == y) //到达末位置,结束循环
    {
        cout << sa.str << endl;
        break;
    }
    int l = a[sa.pot].left, r = a[sa.pot].right, f = a[sa.pot].fath, s = sa.str;    

//以下,对该点子父节点进行遍历
    if (r && b[r]!=1)
    {
        b[r] = 1;
        q.push({ r,s + 1 });
    }
    if (l && b[l]!=1)
    {
        b[l] = 1;
        q.push({ l,s + 1 });
    }
    if (f &&b[f]!=1)
    {
        b[f] = 1;    
        q.push({ f,s + 2 });
    }
}

三.代码展示

#define _CRT_SECURE_NO_WARNINGS

#include<iostream>
#include<queue>
#include<algorithm>
#include<cstring>

using namespace std;
struct poi {
    int left, right, fath, steep;
}a[110];
typedef struct poin {
    int pot, str;
}tr;
queue<tr> q;
int n, x, y;
int b[110];
int wide[110], de = 0, wi = 0;
void dfs(int t)
{
    if (b[t])return;
    b[t] = 1;
    int le = a[t].left, ri = a[t].right, st = a[t].steep;
    de = max(de, st);
    wide[st]++;
    if (le)
    {
        a[le].steep = st + 1;
        dfs(le);
    }
    if (ri)
    {
        a[ri].steep = st + 1;
        dfs(ri);
    }
}

int main()
{
     cin >> n;
    int q1, w;
    for (int i = 1; i < n; i++)
    {
        cin >> q1 >> w;
        if (!a[q1].left)a[q1].left = w;
        else a[q1].right = w;
        a[w].fath = q1;
    }cin >> x >> y;
    
    a[1].steep = 1;
    dfs(1);
    for (int j = 1; j <= n; j++)wi = max(wi, wide[j]);
    cout << de << endl << wi << endl;
    memset(b, -1, sizeof(b));
    
    tr sa = {x,0};
    b[x] = 1;
    q.push(sa);
   
    while (!q.empty())
    {
        sa = q.front();
        q.pop();
      
        if (sa.pot == y) 
        {
            cout << sa.str << endl;
            break;
        }
        int l = a[sa.pot].left, r = a[sa.pot].right, f = a[sa.pot].fath, s = sa.str;
             
        if (r && b[r]!=1)
        {
            b[r] = 1;
            q.push({ r,s + 1 });
        }
        if (l && b[l]!=1)
        {
            b[l] = 1;
            q.push({ l,s + 1 });
        }
        if (f &&b[f]!=1)
        {
            b[f] = 1;
      
            q.push({ f,s + 2 });
        }
    }
    return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值