1 条题解

  • 0
    @ 2026-10-27 12:58:42

    思路与算法

    建立每个编号的孩子表并统计入度。树根是出现过但入度为0的唯一结点。扫描出现的编号,选孩子数最大、并列编号最小的结点,再将其孩子排序输出。单点按约定编号1处理。

    正确性说明

    有根树除根外每点恰有一个父亲,根没有父亲,因此入度0恰好定位根。孩子表直接记录题意给出的所有直接孩子;按孩子数降序、编号升序比较即可满足最优与并列规则,最后排序得到要求的孩子顺序。

    复杂度

    初始化编号数组O(1000),读边O(n),寻找根和最大孩子数O(1000);孩子排序O(n log n),空间O(1000+n)。

    易错点

    n是点数而非最大编号,标签可能到1000且不连续。统计的是直接孩子,不是所有后代。并列选择最小标签。单点输出1、1及空第三行。

    参考代码(C++11)

    #include <bits/stdc++.h>
    using namespace std;
    int main() {
        int n, m;
        cin >> n >> m;
        vector<vector<int>> a(1001);
        vector<int> in(1001), exists(1001);
        for (int i = 0; i < m; ++i) {
            int x, y;
            cin >> x >> y;
            a[x].push_back(y);
            ++in[y];
            exists[x] = exists[y] = 1;
        }
        if (n == 1) {
            cout << "1\n1\n\n";
            return 0;
        }
        int root = 0, best = 0;
        for (int i = 1; i <= 1000; ++i)
            if (exists[i]) {
                if (!in[i])
                    root = i;
                if (!best || a[i].size() > a[best].size())
                    best = i;
            }
        sort(a[best].begin(), a[best].end());
        cout << root << "\n" << best << "\n";
        for (int i = 0; i < (int)a[best].size(); ++i)
            cout << (i ? " " : "") << a[best][i];
        cout << "\n";
    }
    
    • 1

    信息

    ID
    2064
    时间
    1000ms
    内存
    64MiB
    难度
    普及−
    标签
    递交数
    0
    已通过
    0
    上传者