拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

求树的根【牛客tracker 每日一题】

求树的根【牛客tracker  每日一题】

求树的根

时间限制:1 秒
空间限制:256M

网页链接

牛客tracker

牛客tracker & 每日一题,完成每日打卡,即可获得牛币。获得相应数量的牛币,能在【牛币兑换中心】,换取相应奖品!助力每日有题做,丰盈牛币日益多!


描述

给定一棵包含n nn个节点的有根树,节点编号为1 ∼ n 1 \sim n1∼n。输入以n − 1 n - 1n−1条有向边( a i , b i ) (a_i, b_i)(ai​,bi​)表示:存在一条从a i a_iai​指向b i b_ibi​的边,且整棵树构成一棵树。

请输出:


输入描述


输出描述


示例 1

输入:

3 1 2 1 3

输出:

1 2 3

数据范围与提示

解题思路

本题是有根树基本性质统计的入门题。给定一棵有n nn个节点的有根树,边以有向边( a i , b i ) (a_i, b_i)(ai​,bi​)的形式给出(表示a i a_iai​指向b i b_ibi​),要求找出根节点(入度为0 00的唯一节点)和所有叶子节点(出度为0 00的节点),并按升序输出叶子编号。只需统计每个节点的入度和出度,即可在线性时间内完成。

1. 问题等价转化
2. 算法实现
  1. 输入处理:
    • 读入n nn。若n = 1 n = 1n=1,则只有一个节点,它既是根也是叶子,直接输出1和1。
    • 创建两个数组inDeg和outDeg,大小均为n + 1 n+1n+1,初始化为0 00,分别统计每个节点的入度和出度。
    • 循环读入n − 1 n-1n−1条有向边( x , y ) (x, y)(x,y):
      • inDeg[y]++(y yy的入度加一);
      • outDeg[x]++(x xx的出度加一)。
  2. 寻找根节点:
    • 遍历节点编号1 ∼ n 1 \sim n1∼n,找到第一个inDeg[i] == 0的节点,输出其编号,即为根。
  3. 收集叶子节点:
    • 创建vector<ll> leaves。
    • 再次遍历节点编号1 ∼ n 1 \sim n1∼n,若outDeg[i] == 0,则将i ii加入leaves。
    • 由于遍历顺序是从小到大,leaves中元素天然升序,无需额外排序(代码中sort是冗余但无害的)。
  4. 输出叶子:
    • 按顺序输出leaves中的元素,空格分隔,最后换行。
3. 复杂度分析

总结

利用有根树中根节点入度为0 00、叶子节点出度为0 00的性质,只需一次遍历统计度数,即可快速确定根和所有叶子。注意n = 1 n=1n=1的边界情况需特判。该方法简单高效,是树结构基础操作的典型应用。

代码简要说明

代码内容

#include<bits/stdc++.h>usingnamespacestd;#defineendl'\n'typedeflonglongll;typedefunsignedlonglongull;typedefvector<vector<ll>>vvt;typedefpair<ll,ll>pll;constll N=1e3+10;constll INF=1e18;constll M=1e6+10;constll mod=1e9+7;voidsolve(){ll n;cin>>n;if(n==1){cout<<"1\n1\n";return;}vector<ll>a(n+1,0);vector<ll>b(n+1,0);for(ll i=1;i<n;i++){ll x,y;cin>>x>>y;a[y]++;b[x]++;}for(ll i=1;i<=n;i++){if(a[i]==0){cout<<i<<'\n';break;}}vector<ll>c;for(ll i=1;i<=n;i++)if(b[i]==0)c.push_back(i);sort(c.begin(),c.end());for(ll i=0;i<=(ll)c.size()-1;i++)cout<<c[i]<<' ';cout<<'\n';}intmain(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);solve();return0;}
返回列表