CF 1406C Link Cut Centroids

题目描述

https://codeforces.com/contest/1406/problem/C

简要题意:给定一棵 $n$ 个节点的树,求是否可以通过删一条边并且加一条边使得该树的重心唯一,删掉的边和加入的边可以是同一条边

$n\le 10^5$

Solution

根据树的重心的性质,如果有两个重心 $x$ 和 $y$,则 $x$ 和 $y$ 一定直接相连

所以我们不妨砍掉 $y$ 里的一个叶子然后连到 $x$ 上,这样重心就变成了 $x$

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <stack>
#include <queue>
#define ll long long
#define maxn 100010
#define cn const node
#define cQ const Queue
#define INF 1000000000000000000ll
using namespace std;

int n, m;

struct Edge {
int fr, to, next;
} e[maxn * 2]; int c1, head[maxn];
inline void add_edge(int u, int v) {
e[c1].fr = u; e[c1].to = v;
e[c1].next = head[u]; head[u] = c1++;
}

int f[maxn], sz[maxn];
void dfs(int u, int fa) {
sz[u] = 1; f[u] = 0;
for (int i = head[u]; ~i; i = e[i].next) {
int v = e[i].to; if (v == fa) continue ;
dfs(v, u); sz[u] += sz[v]; f[u] = max(f[u], sz[v]);
}
f[u] = max(f[u], n - sz[u]);
}

int ans1, ans2;
void Dfs(int u, int fa) {
bool F = 1;
for (int i = head[u]; ~i; i = e[i].next) {
int v = e[i].to; if (v == fa) continue ;
Dfs(v, u); F = 0;
}
if (F) ans1 = fa, ans2 = u;
}

void clear() {
for (int i = 1; i <= n; ++i) head[i] = -1; c1 = 0;
}

void work() {
cin >> n;
for (int i = 1; i < n; ++i) {
int x, y; cin >> x >> y;
add_edge(x, y); add_edge(y, x);
}
if (n & 1) {
cout << e[1].fr << " " << e[1].to << endl;
cout << e[1].fr << " " << e[1].to << endl;
return clear();
} dfs(1, 0); int p1 = 0, p2 = 0, s = 0;
for (int i = 1; i <= n; ++i) {
if (f[i] < n / 2) continue;
if (f[i] == n / 2 && p1) p2 = i;
else if (f[i] == n / 2) p1 = i;
++s;
}
if (p1 && p2 && s == n) {
Dfs(p2, p1);
cout << ans1 << " " << ans2 << endl;
cout << ans2 << " " << p1 << endl;
clear();
}
else {
cout << e[1].fr << " " << e[1].to << endl;
cout << e[1].fr << " " << e[1].to << endl;
clear();
}
}

int main() {
int T; cin >> T; memset(head, -1, sizeof head);
while (T--) work();
return 0;
}