http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=4045
题意:给一棵树。这棵树有n个节点,问你这个图能不能分成k个分块。这个分块内所有的节点都至少与一个该块中的其他节点有一条边相连。
题目分析:由于是无根树,所以可以随便选取一个结点作为根节点,然后dfs往下搜索,搜索过程不容易划分哪些结点和哪些结点是一块,而利用搜索到叶子结点之后往上回溯的过程,每累积n/k个点就划分一次,就很容易划分出结点块.这道题也主要是利用了dfs的回溯过程.(很多不容易正向解决的问题回溯起来很容易得到解决)
1 #include <iostream> 2 #include <iomanip> 3 #include <algorithm> 4 #include <map> 5 #include <vector> 6 #include <string> 7 #include <set> 8 #include<cstdio> 9 #include <cmath> 10 #include<cstring> 11 using namespace std; 12 typedef long long ll; 13 bool vis[100005]; 14 int dp[100005]; 15 vector<int>G[100005]; 16 int dfs(int u,int k){ 17 vis[u]=1; 18 int t=1; 19 for(int i=0;i<G[u].size();i++){ 20 if(!vis[G[u][i]]){ 21 t+=dfs(G[u][i],k); 22 } 23 } 24 dp[u]=t; 25 if(dp[u]==k){ 26 dp[u]=0; 27 } 28 return dp[u]; 29 } 30 void dfs_ans(int u,int fa){ 31 if(dp[u]==0&&u!=fa)return; 32 vis[u]=1; 33 if(u!=fa){ 34 printf(" %d",u); 35 } 36 for(int i=0;i<G[u].size();i++){ 37 if(!vis[G[u][i]]){ 38 dfs_ans(G[u][i],u); 39 } 40 } 41 } 42 int main(){ 43 //freopen("in.txt","r",stdin); 44 ios_base::sync_with_stdio(0); 45 cin.tie(NULL); 46 int t; 47 cin>>t; 48 while(t--){ 49 int n,k; 50 cin>>n>>k; 51 // cout <<n<<k<<endl; 52 for(int i=1;i<=n;i++)G[i].clear(); 53 memset(vis,0,sizeof(vis)); 54 memset(dp,0,sizeof(dp)); 55 for(int i=0;i<n-1;i++){ 56 int a,b; 57 cin>>a>>b; 58 G[a].push_back(b); 59 G[b].push_back(a); 60 } 61 dfs(1,k); 62 memset(vis,0,sizeof(vis)); 63 //for(int i=0i<n;i++){if(dp[i]==0){dp[i]=1;printf("%d",i);dfs(i,k,i);dp[i]=0;} 64 if(dp[1]==0){ 65 printf("YES "); 66 for(int i=1;i<=n;i++){ 67 if(dp[i]==0){ 68 printf("%d",i); 69 dfs_ans(i,i); 70 printf(" "); 71 } 72 73 } 74 } 75 else{ 76 printf("NO "); 77 } 78 } 79 return 0; 80 }