假如可以分块,其实很容易分析出来,从叶子往上搜,如果没有搜到公共节点,每个块都 + 1,搜到公共节点,如果两边的和小于等于k,就可以合并,继续往上搜,但是如果大于k,就分不了块,其实还有其他情况也是分不了的。
想到了bfs往上搜,就很容易想到dfs,搜到叶子回溯,这样处理起来就方便多了,只要标记下每个块的第一个节点,记录下来,就很容易做了。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int mx = 1e5+10; 4 vector<int> g[mx], tmp; 5 int n, k, cnt; 6 int dep[mx], num[mx], vis[mx]; 7 void dfs(int x, int f){ 8 dep[x] = dep[f] + 1; 9 if(g[x].size()==1&&g[x][0]==f) 10 return; 11 for(int i = 0; i < g[x].size(); i++){ 12 if(g[x][i]==f)continue; 13 dfs(g[x][i], x); 14 if(num[x]) 15 num[x]+=num[g[x][i]]; 16 if(num[x]==k){ 17 cnt++; 18 num[x] = 0; 19 vis[x] = 1; 20 tmp.push_back(x); 21 } 22 } 23 } 24 void dfs2(int x, int f){ 25 if(g[x].size()==1&&g[x][0]==f) 26 return; 27 for(int i = 0; i < g[x].size(); i++){ 28 if(g[x][i]==f)continue; 29 if(vis[g[x][i]] || dep[x]>dep[g[x][i]])continue; 30 printf(" %d", g[x][i]); 31 vis[g[x][i]] = 1; 32 dfs2(g[x][i], x); 33 } 34 } 35 inline void init(){ 36 cnt = 0; 37 for(int i = 1; i <= n; i++) 38 g[i].clear(), num[i] = 1; 39 tmp.clear(); 40 memset(vis, 0, sizeof(vis)); 41 memset(dep, 0, sizeof(dep)); 42 } 43 int main(){ 44 int t; 45 scanf("%d", &t); 46 while(t--){ 47 scanf("%d %d", &n, &k); 48 init(); 49 int u, v; 50 for(int i = 1; i < n; i++){ 51 scanf("%d %d", &u, &v); 52 g[u].push_back(v); 53 g[v].push_back(u); 54 } 55 if(k == 1){ 56 puts("YES"); 57 for(int i = 1; i <= n; i++) 58 printf("%d%c", i, i==n?'\n':' '); 59 continue; 60 } 61 if(k == n){ 62 puts("YES"); 63 for(int i = 1; i <= n; i++) 64 printf("%d\n", i); 65 continue; 66 } 67 dfs(1, 0); 68 if(cnt == n/k){ 69 puts("YES"); 70 for(int i = 0; i < tmp.size(); i++){ 71 printf("%d", tmp[i]); 72 dfs2(tmp[i], tmp[i]); 73 printf("\n"); 74 } 75 } 76 else 77 puts("NO"); 78 } 79 return 0; 80 }