[关闭]
@RabbitHu 2017-08-20T11:42:36.000000Z 字数 1179 阅读 1583

最小森林

题目


题目描述

世上本没有路的,走的人多了,也便变成了路。
——鲁迅

Dev-XYS学长决定在一棵树上散步。

这是一棵一棵个节点的树,Dev-XYS学长在树上走出一条路径(不能经过重复的点),由于Dev-XYS学长走得过快,他路过的点及与这些点相邻的边全都被踩坏了,于是这棵树被去掉一条路径,变成了一个“森林”。

为了回收资源,金企鹅学长跟在Dev-XYS学长后面做清理工作。已知企鹅学长只需回收“森林”中节点数最多的那一棵树,他的“辛苦度”是这一棵树的节点个数。

作为企鹅学长“在OI学术相关方面的真爱”,Dev-XYS学长非常心疼辛勤工作的企鹅学长,他希望走出一条最好的路径,使得企鹅学长“辛苦度”最低。

给出一棵树,求最小“辛苦度”。

输入

第1行:一个整数,表示节点个数。
第2~n行:每行两个整数, 表示之间有一条边。

输出

一行,一个整数,表示最小辛苦度。

样例

样例输入

  1. 5
  2. 1 2
  3. 2 3
  4. 2 4
  5. 4 5

样例输出

  1. 1

样例解释

Dev-XYS学长可以从1号节点走到5号节点,这样森林中只剩下3号节点,企鹅学长只需回收这棵只有一个节点的树即可。

数据范围

提示

这可能是全场最水的题。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cmath>
  4. #include <algorithm>
  5. #include <iostream>
  6. using namespace std;
  7. const int N = 1000005, INF = 0x3f3f3f3f;
  8. int n;
  9. int ecnt, adj[N], nxt[2*N], go[2*N];
  10. int g[N], f[N], size[N];
  11. void add(int u, int v){
  12. go[++ecnt] = v;
  13. nxt[ecnt] = adj[u];
  14. adj[u] = ecnt;
  15. }
  16. void dfs(int u, int pre){
  17. size[u] = 1, f[u] = INF;
  18. int v, son1 = 0, son2 = 0;
  19. for(int e = adj[u]; e; e = nxt[e])
  20. if((v = go[e]) != pre){
  21. dfs(v, u);
  22. size[u] += size[v];
  23. f[u] = min(f[u], f[v]);
  24. if(size[v] >= size[son1])
  25. son2 = son1, son1 = v;
  26. else if(size[v] > size[son2])
  27. son2 = v;
  28. }
  29. g[u] = max(size[son2], g[son1]);
  30. f[u] = min(f[u], max(max(g[son1], g[son2]), n - size[u]));
  31. }
  32. int main(){
  33. scanf("%d", &n);
  34. for(int i = 1, u, v; i < n; i++)
  35. scanf("%d%d", &u, &v), add(u, v), add(v, u);
  36. dfs(1, 0);
  37. printf("%d\n", f[1]);
  38. return 0;
  39. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注