w..学树上莫队的时候回来做了这道题,好久没有这么快地A过题了……
dfs保证相邻的节点在同一个块内,只要当前子树的大小大于等于 ,就将它们分到一个块里,选当前节点为省会,最后有可能会剩下一部分到根的节点不足 个,将它们随便分到一个之前的块里就可以。因为剩下的节点数目 ,任意一个块的大小 ,它们加起来一定 。
#include <cstdio>
#include <vector>
const int N = 1005;
std::vector<int> G[N];
int sta[N], top, be[N], root[N], n, b, cnt;
int read() {
int x = 0; char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9') {
x = (x << 3) + (x << 1) + (c ^ 48);
c = getchar();
}
return x;
}
void dfs(int u, int fa) {
int sz = G[u].size(), now = top;
for (int i = 0; i < sz; ++i) {
int v = G[u][i];
if (v == fa) continue;
dfs(v, u);
if (top - now >= b) {
root[++cnt] = u;
while (top > now) be[sta[top--]] = cnt;
}
}
sta[++top] = u;
}
int main() {
n = read(), b = read();
for (int i = 1; i < n; ++i) {
int u = read(), v = read();
G[u].push_back(v), G[v].push_back(u);
}
dfs(1, 0);
while (top) be[sta[top--]] = cnt;
printf("%d\n", cnt);
for (int i = 1; i <= n; ++i) printf("%d ", be[i]); puts("");
for (int i = 1; i <= cnt; ++i) printf("%d ", root[i]); puts("");
return 0;
}