1. 程式人生 > >[zoj4045][思維+dfs]

[zoj4045][思維+dfs]

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\n"); 66 for(int i=1;i<=n;i++){ 67 if(dp[i]==0){ 68 printf("%d",i); 69 dfs_ans(i,i); 70 printf("\n"); 71 } 72 73 } 74 } 75 else{ 76 printf("NO\n"); 77 } 78 } 79 return 0; 80 }
View Code