Search for a command to run...
Progressive hints first, then the full explanation and implementation when you're ready to cash out.
Review status
AI-generated and still unreviewed. Double-check the details before internalizing them.
Hints
Open only as much as you need to keep the solve alive.
First ask what the final diameter can even be. For , no tree can have diameter less than , and a star has diameter . So the whole problem is really: how many operations to turn the tree into some star?
Pick the future center . If an operation starts at and ends at some vertex , then every vertex on the path from to becomes directly connected to . So one operation can “fix” one downward chain in the tree rooted at .
Vertices already adjacent to do not need to be fixed. The annoying vertices are those at distance at least from . One operation can cover a chain of such vertices, but once a branch splits, one path cannot cover both branches. Trees are rude like that.
Root the tree at . Look at every vertex with at least one child. Each such vertex needs one operation for all but possibly one of its child-subtrees. Another way to package the same count: the number of operations for center equals
unless there are no depth- vertices, in which case it is .
Simplify that count using degrees. For fixed center , it becomes
So minimize by choosing to be a non-leaf if possible. The answer is basically the number of non-leaf vertices, minus if there is at least one non-leaf. For , it is .
The goal is not to make the tree “pretty”. The goal is to minimize the diameter, and then use as few operations as possible to reach that best possible diameter.
For , the only tree has diameter , so the answer is .
For , the minimum possible diameter of any tree is : diameter would mean only two vertices, while a star on vertices has diameter . So we need the minimum number of operations needed to turn the tree into some star.
Understanding one operation
Suppose we want the final star to be centered at vertex .
If we choose and some endpoint , then the operation takes the whole path
and connects every directly to .
So one operation can make all vertices on one simple path from become direct children of .
That is the key. It does not magically fix multiple branches at once. If a subtree splits into two branches, one path can go down only one of them. The other branch needs another operation somewhere. Classic tree nonsense.
Fix a center
Root the tree at .
A vertex is already fine if it is or directly adjacent to . Every other vertex needs to eventually become adjacent to .
Now look at the rooted tree. Each operation starting from can follow one downward path and fix all vertices at distance at least that lie on that path. Therefore, we need to cover all non-adjacent vertices using downward chains.
A very useful way to count this is to look at the number of leaves after rooting at .
Every operation can end at one leaf and fix the whole path from to that leaf. If a leaf is already adjacent to , it needs no operation. Otherwise, that leaf must be the endpoint of some operation, because it has no descendant that could drag it along later.
So, for a chosen center , the needed operations are exactly the number of leaves whose distance from is at least .
Now translate that into degrees.
In the original tree, leaves are exactly vertices with degree . A leaf is adjacent to exactly when it is one of 's leaf neighbors. Thus:
So to minimize operations, choose with as many leaf neighbors as possible.
Let be the number of leaves in the tree, and let
Then the answer is
This also handles the tiny cases naturally. For , both vertices are leaves, each has one leaf neighbor, so , but the diameter is already minimal and no operation is needed. So we special-case with answer .
Why the formula is correct
Lower bound: after choosing the final center , every leaf not adjacent to must be touched by some operation. Since it is a leaf, the only way to make it adjacent to is for an operation path to end at it. One operation has only one endpoint , so it can handle at most one such leaf. Therefore, we need at least
operations.
Upper bound: for every leaf not adjacent to , perform one operation from to that leaf. This makes every vertex on that path adjacent to . After doing this for all such leaves, every vertex is adjacent to : any non-center vertex lies on a path from to some leaf, and if it was not already adjacent, it gets fixed when that leaf is processed.
So the lower bound is achievable. Pick the best center, and we are done.
The solution is just counting leaves and finding the vertex with the most leaf neighbors. Very rude problem statement for such a tiny implementation, honestly.
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<pair<int, int>> edges;
vector<int> deg(n + 1, 0);
for (int i = 0; i < n - 1; i++) {
int u, v;
cin >> u >> v;
edges.push_back({u, v});
deg[u]++;
deg[v]++;
}
if (n == 2) {
cout << 0 << '\n';
continue;
}
int leaves = 0;
for (int i = 1; i <= n; i++) {
if (deg[i] == 1) leaves++;
}
vector<int> leafNeighbors(n + 1, 0);
for (auto [u, v] : edges) {
if (deg[u] == 1) leafNeighbors[v]++;
if (deg[v] == 1) leafNeighbors[u]++;
}
int best = 0;
for (int i = 1; i <= n; i++) {
best = max(best, leafNeighbors[i]);
}
cout << leaves - best << '\n';
}
return 0;
}#include <bits/stdc++.h>
using namespace std;
using ll = long long;
void setIO() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
}
int main() {
setIO();
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
vector<pair<int, int>> edges;
vector<int> deg(n + 1, 0);
for (int i = 0; i < n - 1; i++) {
int u, v;
cin >> u >> v;
edges.push_back({u, v});
deg[u]++;
deg[v]++;
}
if (n == 2) {
cout << 0 << '\n';
continue;
}
int leaves = 0;
for (int i = 1; i <= n; i++) {
if (deg[i] == 1) leaves++;
}
vector<int> leafNeighbors(n + 1, 0);
for (auto [u, v] : edges) {
if (deg[u] == 1) leafNeighbors[v]++;
if (deg[v] == 1) leafNeighbors[u]++;
}
int best = 0;
for (int i = 1; i <= n; i++) {
best = max(best, leafNeighbors[i]);
}
cout << leaves - best << '\n';
}
return 0;
}