1 条题解
-
0
自动搬运
来自洛谷,原作者为

yszkddzyh
回首向来萧瑟处,归去,也无风雨也无晴搬运于
2025-08-24 22:52:36,当前版本为作者最后更新于2023-11-25 19:30:59,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
因为是从根节点开始按任意顺序进行深度优先遍历,所以如果想让一个节点尽可能早地遍历到,那显然就应该先朝它这个方向遍历,但由于是深度优先,所以它能遍历到的最早的序号应该就是它的深度,因为你必须经过它的祖先结点才能到它。
反之,如果想让它尽可能晚地遍历到,那就需要先去把别的点尽量都遍历一遍,但同样地,由于是深度优先,所以你不能把这个节点的子节点先遍历了再遍历这个节点,由此,答案即为所有节点数减这个节点的子树的大小加一。
这样,我们 dfs 预处理出每个节点的深度和子树大小,问题迎刃而解。
注意,代码中存储节点深度和子树大小的两个数组在多测中不需要清空,如果你用
memset会超时第 个点(深受其害)。代码如下:
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 5; vector <int> G[N]; int t, n, siz[N], dep[N]; void dfs(int u, int f){ dep[u] = dep[f] + 1; siz[u] = 1; for(int i = 0; i < G[u].size(); i++){ int v = G[u][i]; if(v == f) continue; dfs(v, u), siz[u] += siz[v]; } return; } int main(){ ios :: sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> t; while(t--){ cin >> n; // memset(dep, 0, sizeof(dep)); // memset(siz, 0, sizeof(siz)); for(int i = 1; i <= n; i++) G[i].clear(); for(int i = 1, u, v; i < n; i++){ cin >> u >> v; G[u].push_back(v); G[v].push_back(u); } dfs(1, 0); for(int i = 1; i <= n; i++) cout << dep[i] << ' ' << n - siz[i] + 1 << '\n'; } return 0; }
- 1
信息
- ID
- 9404
- 时间
- 3000ms
- 内存
- 1024MiB
- 难度
- 2
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者