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.
Treat each operation as a color. Then the task is to color every vertex so that vertices at the same depth have different colors, and every parent-child pair has different colors.
Two obvious cliques give lower bounds: every depth level needs all distinct colors, and for every vertex , the set consisting of and all its children also needs all distinct colors.
So the answer is at least
The key question is whether this lower bound is always enough. Spoiler: yes.
Color the tree depth by depth. When coloring one level, each vertex only forbids one color: its parent's color. The vertices in this level also need distinct colors.
Use the lower-bound value . Greedily assign unused colors on a level. If the last remaining color equals the last vertex's forbidden color, swap with an earlier vertex whose forbidden color is different. Such a vertex must exist, or one parent would have children, contradicting .
Turn Operations Into Colors
Call operation color , operation color , and so on. If a vertex is painted during operation , say its color is .
Then one operation is valid exactly when all vertices in it:
So we need color all vertices with as few colors as possible such that:
Depth can be counted from or ; only equality of depths matters, so who cares. Classic off-by-one drama, but harmless.
The Lower Bound
There are two unavoidable cliques in the conflict graph.
First, all vertices at the same depth conflict with each other, so if
then we need at least colors.
Second, take any vertex and all of its children. The children are all at the same depth, so they pairwise conflict. Also every child conflicts with by an edge. Therefore this whole set needs distinct colors.
If is the number of children of , then we need at least
colors for every .
So the answer is at least
The nice part: this is also always enough.
Why This Bound Is Enough
We color the tree level by level from the root downward.
Suppose all previous levels are already colored correctly. Now consider one depth level .
Every vertex has exactly one forbidden color: the color of its parent. We need assign all vertices in distinct colors, avoiding each vertex's forbidden color.
Since , there are enough colors in raw quantity.
The only possible annoying case is when a lot of vertices all forbid the same color. But vertices forbidding some color are exactly children of the unique vertex on the previous level colored ; colors on one level are already distinct. That parent has at most children.
So no color is forbidden by vertices on the same level.
That is precisely what we need. If a level has fewer than vertices, there is slack. If it has exactly vertices, then not all of them can forbid the same color, because that would mean one parent has children, which would force at least colors. Not happening with our definition of .
Greedy Construction
For one level, keep the set of unused colors.
Process vertices in any order:
This can only fail if the unused set contains exactly one color, and that color is forbidden by the current vertex.
When that happens, we are at the last vertex of a full level of size . Let the stuck forbidden color be .
Because not every vertex on this level forbids , there is an earlier vertex whose forbidden color is not .
Swap:
This is valid because:
That's it. No giant matching machinery needed. We bully the one bad case with a swap and move on.
Correctness Proof
Let
First, operations are necessary. Every depth level is a clique under the rules, so at least operations are needed. Also, for every vertex , the set containing and all children of is a clique, so at least operations are needed. Therefore any answer needs at least operations.
Now we prove the construction uses exactly colors and is valid.
During the coloring of one depth level, all assigned colors are chosen from unused colors, so vertices on that level get pairwise distinct colors. We also never assign a vertex its parent's color, except possibly in the stuck case before the swap; after the swap, both affected vertices are valid.
The stuck case can happen only when the current level has size and only one unused color remains, with equal to the current vertex's forbidden color. If all previous vertices also forbade , then all vertices on this level would be children of the same parent color. Since colors on the previous level are distinct, that means one parent has children. But then , impossible. So some previous vertex forbids a different color, and the swap exists.
Thus every level can be colored. Since parent-child colors differ and same-depth colors differ, every operation group is valid.
The construction uses colors, and we already proved fewer than is impossible, so it is optimal.
Complexity
Each vertex is processed once. Set operations cost , so the total complexity is
per total input size, which is easily fine for vertices. Memory is .
#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<vector<int>> g(n + 1);
for (int i = 0; i < n - 1; i++) {
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
vector<int> parent(n + 1, 0), depth(n + 1, 0), order;
order.reserve(n);
queue<int> q;
q.push(1);
parent[1] = -1;
while (!q.empty()) {
int v = q.front();
q.pop();
order.push_back(v);
for (int to : g[v]) {
if (to == parent[v]) continue;
parent[to] = v;
depth[to] = depth[v] + 1;
q.push(to);
}
}
int maxDepth = 0;
for (int v = 1; v <= n; v++) maxDepth = max(maxDepth, depth[v]);
vector<vector<int>> level(maxDepth + 1);
for (int v = 1; v <= n; v++) level[depth[v]].push_back(v);
int maxWidth = 0;
for (auto &vec : level) maxWidth = max(maxWidth, (int)vec.size());
vector<int> childCount(n + 1, 0);
int maxChildren = 0;
for (int v = 2; v <= n; v++) {
childCount[parent[v]]++;
maxChildren = max(maxChildren, childCount[parent[v]]);
}
int k = max(maxWidth, maxChildren + 1);
vector<int> color(n + 1, 0);
for (int d = 0; d <= maxDepth; d++) {
set<int> unused;
for (int c = 1; c <= k; c++) unused.insert(c);
vector<int> forbidden;
forbidden.reserve(level[d].size());
for (int i = 0; i < (int)level[d].size(); i++) {
int v = level[d][i];
int bad = (v == 1 ? 0 : color[parent[v]]);
forbidden.push_back(bad);
auto it = unused.begin();
if (it != unused.end() && *it == bad) ++it;
if (it != unused.end()) {
color[v] = *it;
unused.erase(it);
} else {
int pos = -1;
for (int j = 0; j < i; j++) {
if (forbidden[j] != bad) {
pos = j;
break;
}
}
int u = level[d][pos];
color[v] = color[u];
color[u] = bad;
unused.erase(bad);
}
}
}
vector<vector<int>> ops(k + 1);
for (int v = 1; v <= n; v++) ops[color[v]].push_back(v);
cout << k << '\n';
for (int c = 1; c <= k; c++) {
cout << ops[c].size();
for (int v : ops[c]) cout << ' ' << v;
cout << '\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<vector<int>> g(n + 1);
for (int i = 0; i < n - 1; i++) {
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
vector<int> parent(n + 1, 0), depth(n + 1, 0), order;
order.reserve(n);
queue<int> q;
q.push(1);
parent[1] = -1;
while (!q.empty()) {
int v = q.front();
q.pop();
order.push_back(v);
for (int to : g[v]) {
if (to == parent[v]) continue;
parent[to] = v;
depth[to] = depth[v] + 1;
q.push(to);
}
}
int maxDepth = 0;
for (int v = 1; v <= n; v++) maxDepth = max(maxDepth, depth[v]);
vector<vector<int>> level(maxDepth + 1);
for (int v = 1; v <= n; v++) level[depth[v]].push_back(v);
int maxWidth = 0;
for (auto &vec : level) maxWidth = max(maxWidth, (int)vec.size());
vector<int> childCount(n + 1, 0);
int maxChildren = 0;
for (int v = 2; v <= n; v++) {
childCount[parent[v]]++;
maxChildren = max(maxChildren, childCount[parent[v]]);
}
int k = max(maxWidth, maxChildren + 1);
vector<int> color(n + 1, 0);
for (int d = 0; d <= maxDepth; d++) {
set<int> unused;
for (int c = 1; c <= k; c++) unused.insert(c);
vector<int> forbidden;
forbidden.reserve(level[d].size());
for (int i = 0; i < (int)level[d].size(); i++) {
int v = level[d][i];
int bad = (v == 1 ? 0 : color[parent[v]]);
forbidden.push_back(bad);
auto it = unused.begin();
if (it != unused.end() && *it == bad) ++it;
if (it != unused.end()) {
color[v] = *it;
unused.erase(it);
} else {
int pos = -1;
for (int j = 0; j < i; j++) {
if (forbidden[j] != bad) {
pos = j;
break;
}
}
int u = level[d][pos];
color[v] = color[u];
color[u] = bad;
unused.erase(bad);
}
}
}
vector<vector<int>> ops(k + 1);
for (int v = 1; v <= n; v++) ops[color[v]].push_back(v);
cout << k << '\n';
for (int c = 1; c <= k; c++) {
cout << ops[c].size();
for (int v : ops[c]) cout << ' ' << v;
cout << '\n';
}
}
return 0;
}