codeforces1528c_us open of surfing

codeforces1528c_us open of surfingCodeForces 1073F Choosing Two Paths

大家好,又见面了,我是你们的朋友全栈君。

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

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

Output

3 6
7 5

Input

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

Output

2 9
6 8

Input

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

Output

10 6
4 5

Input

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

Output

9 11
8 10

Note

The picture corresponding to the first example:

img

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:

img

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:

img

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:

img

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,则尝试更新答案
#include <bits/stdc++.h> using namespace std; const int maxn = 200011; struct triple { triple(int _u = 0, int _v1 = 0, int _v2 = 0) : u(_u), v1(_v1), v2(_v2) {} int u, v1, v2; bool operator<(const triple &b) const {return u < b.u;} }; vector<int> w[maxn]; int deg[maxn], dep[maxn]; int x1, y1, x2, y2; pair<pair<int, int>, triple> val[maxn]; // <<deg=3的后代(u)的最大深度, u到两个最远后代(v1, v2)的距离之和>, <u, v1, v2>> pair<int, int> ans; pair<int, int> mxdep[maxn], updis[maxn]; // <最远距离, u> vector<pair<pair<int, int>, int>> downdis[maxn]; // <<后代(u)的最大深度, u>, 到该后代的路径上的第一个点> void dfs1(int u, int d, int pre) { dep[u] = d; mxdep[u] = make_pair(d, u); for (int v : w[u]) { if (v == pre) continue; dfs1(v, d + 1, u); mxdep[u] = max(mxdep[u], mxdep[v]); downdis[u].push_back(make_pair(mxdep[v], v)); } sort(downdis[u].begin(), downdis[u].end(), greater<pair<pair<int, int>, int>>()); } void dfs2(int u, int pre) { if (~pre) { updis[u] = make_pair(1 + updis[pre].first, updis[pre].second); auto tp = downdis[pre][0].second == u ? downdis[pre][1].first : downdis[pre][0].first; if (downdis[pre].size() > 1) { updis[u] = max(updis[u], make_pair(tp.first + 1, tp.second)); } } else { updis[u] = make_pair(0, u); } for (int v : w[u]) { if (v == pre) continue; dfs2(v, u); } } void dfs3(int u, int pre) { vector<pair<pair<pair<int, int>, triple>, int>> vec; for (int v : w[u]) { if (v == pre) continue; dfs3(v, u); if (val[v].first.first) { vec.push_back(make_pair(val[v], v)); } } if (vec.size() >= 2) { sort(vec.begin(), vec.end(), greater<pair<pair<pair<int, int>, triple>, int>>()); auto &x = vec[0].first, &y = vec[1].first; val[u] = x; int a = x.first.first + y.first.first - 2 * dep[u]; int b = x.first.second + y.first.second; auto c = make_pair(a, b); if (c > ans) { ans = c; x1 = x.second.v1, y1 = y.second.v1; x2 = x.second.v2, y2 = y.second.v2; } } else { if (vec.size() == 1) { val[u] = vec[0].first; } else if (deg[u] >= 3) { assert(downdis[u].size() >= 2); auto &x = downdis[u][0].first, &y = downdis[u][1].first; int tp = x.first + y.first - 2 * dep[u]; val[u] = make_pair(make_pair(dep[u], tp), triple(u, x.second, y.second)); } else { val[u] = make_pair(make_pair(0, 0), triple()); } if (vec.size() == 1 && deg[u] >= 3) { vector<pair<int, int>> cand; cand.push_back(updis[u]); int up = min(3, (int)downdis[u].size()); for (int i = 0; i < up; ++i) { if (downdis[u][i].second == vec[0].second) continue; cand.push_back(downdis[u][i].first); } assert(cand.size() >= 2); sort(cand.begin(), cand.end(), greater<pair<int, int>>()); auto &x = vec[0].first; int a = x.first.first - dep[u]; int b = x.first.second + cand[0].first + cand[1].first; auto c = make_pair(a, b); if (c > ans) { ans = c; x1 = x.second.v1, y1 = cand[0].second; x2 = x.second.v2, y2 = cand[1].second; } } } } int main() { int n; scanf("%d", &n); for (int i = 1; i < n; ++i) { int u, v; scanf("%d%d", &u, &v); w[u].push_back(v); w[v].push_back(u); ++deg[u]; ++deg[v]; } ans = make_pair(0, 0); dfs1(1, 0, -1); dfs2(1, -1); dfs3(1, -1); printf("%d %d\n%d %d\n", x1, y1, x2, y2); return 0; }

转载于:https://www.cnblogs.com/hitgxz/p/9977668.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107195.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java p12证书_java引用微信支付的p12证书文件

    java p12证书_java引用微信支付的p12证书文件最近对接微信支付的退款功能,其中涉及到引用证书文件。1.绝对路径://windows:publicstaticStringPATH1=”E:\\project_ceshi\\apiclient_cert.p12″;//linuxpublicstaticStringPATH2=”/home/www/ceshi/apiclient_cert.p12″;使用决定路径时,直接引用即可…

    2022年6月23日
    124
  • set集合的特点

    set集合的特点set集合的特点A:存入集合的顺序和取出集合的顺序不一致B:没有索引C:存入集合的元素没有重复set接口的实现类常用的有HashSet和TreeSet类。语法格式如下:Set<String>set1=newHashSet<String>();Set<String>set2=newTreeSe…

    2022年6月4日
    30
  • 概率论知识点总结

    概率论知识点总结概率论与数理统计知识点总结 持续更新 文章目录概率论与数理统计知识点总结 持续更新 第一章 概率论的基本概念第二章 随机变量及其分布第一章 概率论的基本概念 1 样本空间 对于随机试验来说 由于可以事先明确试验所有可能的结果 因此称随机试验所有可能结果的集合为随机试验的样本空间 记为 Omega 称随机试验中一个可能结果为一个样本点 记为 omega 从而样本空间就是样本点的集合 即 Omega omega 2 随机事件 一般的 称随机试验的样本空间 Ome

    2025年12月1日
    5
  • IPFS挖矿奖励分配机制,如何获得更大的出快机会,水滴科技Filecoin扇区封装及挖矿流程是怎样的?[通俗易懂]

    IPFS挖矿奖励分配机制,如何获得更大的出快机会,Filecoin扇区封装及挖矿流程是怎样的?Filecoin挖矿奖励区块奖励方面,在Filecoin总量20亿的FIL通证中,可以通过挖矿获得的部分为70%。其余为开发团队(15%)、投资人(10%),基金会(5%)的份额。就区块奖励而言,可挖通证的50%将在6年内挖出。目前奖励的具体参数还没有最终确定,当前测试网Filecoin区块奖励模型由“简单供给+网络基线供给”构成。  不少业内人士推测,在网络达到一定的目标存储规模之前,矿工的奖励会延迟

    2022年4月14日
    65
  • 一文教你了解SSL协议「建议收藏」

    一文教你了解SSL协议「建议收藏」什么是SSL简称是SSL,全称SecureSocketsLayer安全套接字协议,一般我们在学习SSL的时候,都会和TLS一起来学习的,为什么呢?因为SSL和TLS都是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层与应用层之间对网络连接进行加密。我们先看SSL协议,然后在看TLS协议。SSL协议位于TCP/IP协议与各种应用层协议之间,为数据通讯提供安全支持。SSL协议可分为两层: SSL记录协议(SSLRecordProtocol)

    2022年5月31日
    38
  • 根据sessionid获取session对象_sessionattributes注解

    根据sessionid获取session对象_sessionattributes注解session.setAttribute(“sessionName”,Object);用来设置session值的,sessionName是名称,object是你要保存的对象。session.getAttribute(“sessionName”);用来得到对应名称的session值,即得到object对象,注意需要进行类型转换!

    2022年10月7日
    6

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号