Description

You are given an undirected unweighted tree consisting of \(n\) vertices.

An undirected tree is a connected undirected graph with \(n−1\) edges.

Your task is to choose two pairs of vertices of this tree (all the chosen vertices should be distinct) \((x_1,y_1)\) and \((x_2,y_2)\) in such a way that neither \(x_1\) nor \(y_1\) belong to the simple path from \(x_2\) to \(y_2\) and vice versa (neither \(x_2\) nor \(y_2\) should not belong to the simple path from \(x_1\) to \(y_1\)).

It is guaranteed that it is possible to choose such pairs for the given tree.

Among all possible ways to choose such pairs you have to choose one with the maximum number of common vertices between paths from \(x_1\) to \(y_1\) and from \(x_2\) to \(y_2\). And among all such pairs you have to choose one with the maximum total length of these two paths.

It is guaranteed that the answer with at least two common vertices exists for the given tree.

The length of the path is the number of edges in it.

The simple path is the path that visits each vertex at most once.

Input

The first line contains an integer \(n\) — the number of vertices in the tree \((6 \le n \le 2 \cdot 10^5)\).

Each of the next \(n−1\) lines describes the edges of the tree.

Edge \(i\) is denoted by two integers \(u_i\) and \(v_i\), the labels of vertices it connects \((1\le u_i,v_i\le n, u_i \neq v_i)\).

It is guaranteed that the given edges form a tree.

It is guaranteed that the answer with at least two common vertices exists for the given tree.

Output

Print any two pairs of vertices satisfying the conditions described in the problem statement.

It is guaranteed that it is possible to choose such pairs for the given tree.

Examples

Input

  1. 7
  2. 1 4
  3. 1 5
  4. 1 6
  5. 2 3
  6. 2 4
  7. 4 7

Output

  1. 3 6
  2. 7 5

Input

  1. 9
  2. 9 3
  3. 3 5
  4. 1 2
  5. 4 3
  6. 4 7
  7. 1 7
  8. 4 6
  9. 3 8

Output

  1. 2 9
  2. 6 8

Input

  1. 10
  2. 6 8
  3. 10 3
  4. 3 7
  5. 5 8
  6. 1 7
  7. 7 2
  8. 2 9
  9. 2 8
  10. 1 4

Output

  1. 10 6
  2. 4 5

Input

  1. 11
  2. 1 2
  3. 2 3
  4. 3 4
  5. 1 5
  6. 1 6
  7. 6 7
  8. 5 8
  9. 5 9
  10. 4 10
  11. 4 11

Output

  1. 9 11
  2. 8 10

Note

The picture corresponding to the first example:

The intersection of two paths is \(2\) (vertices \(1\) and \(4\)) and the total length is \(4+3=7\).

The picture corresponding to the second example:

The intersection of two paths is \(2\) (vertices \(3\) and \(4\)) and the total length is \(5+3=8\).

The picture corresponding to the third example:

The intersection of two paths is \(3\) (vertices \(2\), \(7\) and \(8\)) and the total length is \(5+5=10\).

The picture corresponding to the fourth example:

The intersection of two paths is \(5\)(vertices \(1\), \(2\), \(3\), \(4\) and \(5\)) and the total length is \(6+6=12\).

Solution

题意:给定一棵树,找两组点\((x_1, y_1)\)和\((x_2, y_2)\),使得\(x_1,y_1\)不在\(x_2\)和\(y_2\)之间的路径上,\(x_2,y_2\)不在\(x_1\)和\(y_1\)之间的路径上,要求:

  • \(x_1,y_1\)之间的路径与\(x_2,y_2\)之间的路径的重合边数最多
  • 满足第一个条件的前提下,两条路径的长度之和最大

我们考虑两条路径的公共路径,不妨记作\((x, y)\),\(x\)和\(y\)的LCA记作\(a\),则\(a\)或者是\(x\)和\(y\)中的一个,或者是\(x\)与\(y\)路径上的其他节点,所以我们先求出每个点的度大于2的后代的最大深度,以及每个点往父亲方向能够到达的最远距离,然后再一次DFS,对于任何一个点\(u\):

  • 如果\(u\)有两个孩子节点具有度大于2的后代,则尝试更新答案
  • 否则,若\(u\)只有一个孩子节点具有度大于2的后代,且\(u\)自身的度大于2,则尝试更新答案
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 200011;
  4. struct triple {
  5. triple(int _u = 0, int _v1 = 0, int _v2 = 0) : u(_u), v1(_v1), v2(_v2) {}
  6. int u, v1, v2;
  7. bool operator<(const triple &b) const {return u < b.u;}
  8. };
  9. vector<int> w[maxn];
  10. int deg[maxn], dep[maxn];
  11. int x1, y1, x2, y2;
  12. pair<pair<int, int>, triple> val[maxn]; // <<deg=3的后代(u)的最大深度, u到两个最远后代(v1, v2)的距离之和>, <u, v1, v2>>
  13. pair<int, int> ans;
  14. pair<int, int> mxdep[maxn], updis[maxn]; // <最远距离, u>
  15. vector<pair<pair<int, int>, int>> downdis[maxn]; // <<后代(u)的最大深度, u>, 到该后代的路径上的第一个点>
  16. void dfs1(int u, int d, int pre) {
  17. dep[u] = d;
  18. mxdep[u] = make_pair(d, u);
  19. for (int v : w[u]) {
  20. if (v == pre) continue;
  21. dfs1(v, d + 1, u);
  22. mxdep[u] = max(mxdep[u], mxdep[v]);
  23. downdis[u].push_back(make_pair(mxdep[v], v));
  24. }
  25. sort(downdis[u].begin(), downdis[u].end(), greater<pair<pair<int, int>, int>>());
  26. }
  27. void dfs2(int u, int pre) {
  28. if (~pre) {
  29. updis[u] = make_pair(1 + updis[pre].first, updis[pre].second);
  30. auto tp = downdis[pre][0].second == u ? downdis[pre][1].first : downdis[pre][0].first;
  31. if (downdis[pre].size() > 1) {
  32. updis[u] = max(updis[u], make_pair(tp.first + 1, tp.second));
  33. }
  34. } else {
  35. updis[u] = make_pair(0, u);
  36. }
  37. for (int v : w[u]) {
  38. if (v == pre) continue;
  39. dfs2(v, u);
  40. }
  41. }
  42. void dfs3(int u, int pre) {
  43. vector<pair<pair<pair<int, int>, triple>, int>> vec;
  44. for (int v : w[u]) {
  45. if (v == pre) continue;
  46. dfs3(v, u);
  47. if (val[v].first.first) {
  48. vec.push_back(make_pair(val[v], v));
  49. }
  50. }
  51. if (vec.size() >= 2) {
  52. sort(vec.begin(), vec.end(), greater<pair<pair<pair<int, int>, triple>, int>>());
  53. auto &x = vec[0].first, &y = vec[1].first;
  54. val[u] = x;
  55. int a = x.first.first + y.first.first - 2 * dep[u];
  56. int b = x.first.second + y.first.second;
  57. auto c = make_pair(a, b);
  58. if (c > ans) {
  59. ans = c;
  60. x1 = x.second.v1, y1 = y.second.v1;
  61. x2 = x.second.v2, y2 = y.second.v2;
  62. }
  63. } else {
  64. if (vec.size() == 1) {
  65. val[u] = vec[0].first;
  66. } else if (deg[u] >= 3) {
  67. assert(downdis[u].size() >= 2);
  68. auto &x = downdis[u][0].first, &y = downdis[u][1].first;
  69. int tp = x.first + y.first - 2 * dep[u];
  70. val[u] = make_pair(make_pair(dep[u], tp), triple(u, x.second, y.second));
  71. } else {
  72. val[u] = make_pair(make_pair(0, 0), triple());
  73. }
  74. if (vec.size() == 1 && deg[u] >= 3) {
  75. vector<pair<int, int>> cand;
  76. cand.push_back(updis[u]);
  77. int up = min(3, (int)downdis[u].size());
  78. for (int i = 0; i < up; ++i) {
  79. if (downdis[u][i].second == vec[0].second) continue;
  80. cand.push_back(downdis[u][i].first);
  81. }
  82. assert(cand.size() >= 2);
  83. sort(cand.begin(), cand.end(), greater<pair<int, int>>());
  84. auto &x = vec[0].first;
  85. int a = x.first.first - dep[u];
  86. int b = x.first.second + cand[0].first + cand[1].first;
  87. auto c = make_pair(a, b);
  88. if (c > ans) {
  89. ans = c;
  90. x1 = x.second.v1, y1 = cand[0].second;
  91. x2 = x.second.v2, y2 = cand[1].second;
  92. }
  93. }
  94. }
  95. }
  96. int main() {
  97. int n;
  98. scanf("%d", &n);
  99. for (int i = 1; i < n; ++i) {
  100. int u, v;
  101. scanf("%d%d", &u, &v);
  102. w[u].push_back(v);
  103. w[v].push_back(u);
  104. ++deg[u]; ++deg[v];
  105. }
  106. ans = make_pair(0, 0);
  107. dfs1(1, 0, -1);
  108. dfs2(1, -1);
  109. dfs3(1, -1);
  110. printf("%d %d\n%d %d\n", x1, y1, x2, y2);
  111. return 0;
  112. }

CodeForces 1073F Choosing Two Paths的更多相关文章

  1. [codeforces 293]B. Distinct Paths

    [codeforces 293]B. Distinct Paths 试题描述 You have a rectangular n × m-cell board. Some cells are alrea ...

  2. Codeforces 219D. Choosing Capital for Treeland (树dp)

    题目链接:http://codeforces.com/contest/219/problem/D 树dp //#pragma comment(linker, "/STACK:10240000 ...

  3. Codeforces 219D Choosing Capital for Treeland

    http://codeforces.com/problemset/problem/219/D 题目大意: 给出一棵树,但是它的边是有向边,选择一个城市,问最少调整多少条边的方向能使一个选中城市可以到达 ...

  4. (纪念第一道完全自己想的树DP)CodeForces 219D Choosing Capital for Treeland

    Choosing Capital for Treeland time limit per test 3 seconds memory limit per test 256 megabytes inpu ...

  5. CodeForces 219D Choosing Capit

    题目链接:http://codeforces.com/contest/219/problem/D 题目大意: 给定一个n个节点的数和连接n个节点的n - 1条有向边,现在要选定一个节点作为起始节点,从 ...

  6. Codeforces 219D - Choosing Capital for Treeland(树形dp)

    http://codeforces.com/problemset/problem/219/D 题意 给一颗树但边是单向边,求至少旋转多少条单向边的方向,可以使得树上有一点可以到达树上任意一点,若有多个 ...

  7. 【CodeForces】870 F. Paths

    [题目]F. Paths [题意]给定数字n,图上有编号为1~n的点,两点当且仅当gcd(u,v)≠1时有连边,定义d(u,v)为两点间最短距离(若不连通则为0),求Σd(u,v),1<=u&l ...

  8. Codeforces 219D Choosing Capital for Treeland:Tree dp

    题目链接:http://codeforces.com/problemset/problem/219/D 题意: 给你一棵树,n个节点. 树上的边都是有向边,并且不一定是从父亲指向儿子的. 你可以任意翻 ...

  9. Codeforces 643G - Choosing Ads(线段树)

    Codeforces 题目传送门 & 洛谷题目传送门 首先考虑 \(p>50\) 的时候怎么处理,也就是求一个区间的绝对众数.我们知道众数这个东西是不能用线段树直接维护的,因为对于区间 ...

随机推荐

  1. sql server对并发的处理-乐观锁和悲观锁(转)

    假如两个线程同时修改数据库同一条记录,就会导致后一条记录覆盖前一条,从而引发一些问题. 例如: 一个售票系统有一个余票数,客户端每调用一次出票方法,余票数就减一. 情景: 总共300张票,假设两个售票 ...

  2. spring定时任务表达式

    @Scheduled 注解 cron表达式 一个cron表达式有至少6个(也可能7个)有空格分隔的时间元素. 按顺序依次为 秒(0~59) 分钟(0~59) 小时(0~23) 天(月)(0~31,但是 ...

  3. winform中容器是如使用的

    1.容器 (1)FlowLayouPanel 普通容器[内部流式布局] (2)Groupbox 带有标题的普通容器[内部普通布局,超出范围隐藏] (3)Panel 普通容器[内部普通布局,超出范围隐藏 ...

  4. django -- Celery实现异步任务

    1. 环境 python==2.7 djang==1.11.2 # 1.8, 1.9, 1.10应该都没问题 celery-with-redis==3.0 # 需要用到redis作为中间人服务(Bro ...

  5. Software Engineer’s path to the best annual performance review

    http://michaelscodingspot.com/2017/06/04/software-engineers-path-best-annual-performance-review/ How ...

  6. elasticsearch报错之 memory locking requested for elasticsearch process but memory is not locked

    安装elasticsearch报错如下: [2019-01-14T03:57:16,453][ERROR][o.e.b.Bootstrap ] [ip-172-31-30-62.ec2.interna ...

  7. idea本地将本地现有的项目和gitlab进行管理并提交到线上

    备注:通过这个操作可以让本地的项目与远程gitlab进行关联,并将本地的代码提交到gitlab上面 1.在idea的菜单项选择 VCS>Import into Version Control&g ...

  8. SDN2017 第三次实验作业

    实验目的 在给定如上实验拓扑情况下,用vlan得到下列虚拟网段 h1--h4互通 h2--h5互通 h3--h6互通 其余主机间无法通信 实验步骤 1. 创建拓扑 #! /usr/bin/python ...

  9. Django商城项目笔记No.14用户部分-用户中心邮箱绑定

    保存邮箱界面如下 接口设计如下 视图逻辑: 因为url是不接受pk参数的,所以UpdateApiView无法确定要更新哪个模型类,所以要重写get_object,告诉他更新哪个模型类.这里更新的是us ...

  10. Eclipse 中怎样自动格式化代码?

    首先 有一个 检查代码风格的工具叫checkstyle,具体怎么下载,请自行百度.. 当你在eclipse安装好 checkstyle后,对于使用google标准的人来说,选择一个项目,右键,点击ch ...