【洛谷P3884】二叉树问题[JLOI2009]

这个主要是二叉树的大杂烩

[JLOI2009] 二叉树问题

题目描述

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

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

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

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

输入格式

第一行是一个整数,表示树的结点个数 n
接下来 n1 行,每行两个整数 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

提示

对于全部的测试点,保证 1u,v,x,yn100,且给出的是一棵树。保证 uv 的父结点。

解法&&个人感想

这个题目就是求深度、宽度和距离
深度顾名思义就是用DFS 而宽度在没有用广度优先遍历的情况下(本题数据较小)就可以比较同一深度的节点数
距离固然可以用LCA(最近公共祖先)但是一看数据范围这样 而且是稀疏图 可以用Floyd求最短路(O(N3))
我们来介绍一下Floyd 其实就是一个类似DP的操作
也就是松弛操作 d[i][j]=min(d[i][j],d[i][k]+d[k][j])
有点像三角形两边之和大于第三边 但是图论里没这回事
这个有时候在全源最短路径里有奇效
P.S:注意本题对“距离”的定义 以及Floyd要用邻接矩阵存储

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int INF=1e9;
int d[105][105];
int head[1005],nex[10005],ver[10005];
int siz[105];
int vis[105];
int n,x,y,tot,sx,sy;
int bro[105];
int ans,sum;
void add(int x,int y){
    ver[++tot]=y;
    nex[tot]=head[x];
    head[x]=tot;
}
void dfs(int x){
    if(vis[x]) return ;
    vis[x]=1;
    for(int i=head[x];i;i=nex[i]){
        int y=ver[i];
        if(vis[y]==0){
            siz[y]=siz[x]+1;
            dfs(y);
        }
    }
}
int main(){
    scanf("%d",&n);
    memset(d,0x3f,sizeof(d));
    for(int i=1;i<=n;i++) d[i][i]=0;
    for(int i=1;i<=n-1;i++){
        scanf("%d%d",&x,&y);
        add(x,y);
        d[x][y]=1;
        d[y][x]=2;
    }
    scanf("%d%d",&sx,&sy);
    siz[1]=1;
    dfs(1);
    for(int i=1;i<=n;i++){
        sum=max(sum,siz[i]);
    }
    printf("%d\n",sum);
    for(int i=1;i<=n;i++){
        bro[siz[i]]++;
    }
    for(int i=1;i<=n-1;i++){
        ans=max(bro[i],ans);
    }
    printf("%d\n",ans);
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
            }
        }
    }
    printf("%d",d[sx][sy]);
    system("pause");
    return 0;
}

  

posted @   Elainafan  阅读(12)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
点击右上角即可分享
微信分享提示