ZOJ - 4045District Division dfs劃分子樹
阿新 • • 發佈:2019-03-12
int oid targe while size style turn hid 不足
ZOJ - 4045District Division
題目大意:給你n個節點的樹,然後讓你劃分這棵數使得,每一塊都恰好k個節點並且兩兩間是連通的,也就是劃分成n/k個連通集,如果可以輸出YES,並輸出對應的劃分,否則輸出NO
一開始覺得是樹形dp,但不知道如何下手,看大佬的做法才恍然大悟,其實就是找子樹大小剛好是k的節點,剛讓它作為這一分塊的根節點,它的父節點就不再記錄它的子樹大小,詳情見代碼
1 #include<cstdio> 2 #include<vector> 3 using namespace std; 4 const int多想一想N=100118; 5 struct Side{ 6 int v,ne; 7 }S[2*N]; 8 vector<int> ans; 9 int n,k,is,m,sn; 10 int head[N],size[N],book[N]; 11 void add(int u,int v) 12 { 13 S[sn].v=v; 14 S[sn].ne=head[u]; 15 head[u]=sn++; 16 } 17 void fp(int u,int f) 18 { 19 for(int i=head[u];i!=-1;i=S[i].ne) 20 if(S[i].v!=f&&!book[S[i].v]) 21 { 22 book[S[i].v]=u; 23 printf(" %d",S[i].v); 24 fp(S[i].v,u); 25 } 26 } 27 int dfs(int u,int f) 28 { 29 if(!is) 30 return 0; 31 size[u]=1; 32 for(int i=head[u];i!=-1;i=S[i].ne) 33 { 34 if(S[i].v!=f&&!book[S[i].v]) 35 dfs(S[i].v,u); 36 if(S[i].v!=f&&!book[S[i].v])//如果它的這個子節點沒有作為劃分的子樹的根節點 37 size[u]+=size[S[i].v];//那麽統計上它的大小 38 } 39 if(size[u]>k)//如果它的子樹大小大於k那麽它分出一個大小k的子樹後 40 return is=0;//剩下的會不足k個 41 if(size[u]==k) 42 { 43 ans.push_back(u);//保存作為劃分的子樹根節點的節點 44 book[u]=f;//並保存它的父節點,不然在輸出時會PE 45 } 46 return 1; 47 } 48 int main() 49 { 50 int t,a,b; 51 scanf("%d",&t); 52 while(t--) 53 { 54 scanf("%d%d",&n,&k); 55 ans.clear(); 56 for(int i=1;i<=n;i++) 57 book[i]=0,head[i]=-1; 58 sn=0; 59 for(int i=0;i<n-1;i++) 60 { 61 scanf("%d%d",&a,&b); 62 add(a,b),add(b,a); 63 } 64 is=1; 65 if(dfs(1,-1)) 66 { 67 printf("YES\n"); 68 for(int i=0;i<ans.size();i++) 69 { 70 printf("%d",ans[i]); 71 fp(ans[i],book[ans[i]]); 72 printf("\n"); 73 } 74 } 75 else 76 printf("NO\n"); 77 } 78 return 0; 79 }
ZOJ - 4045District Division dfs劃分子樹