ZOJ - 4045District Division dfs划分子树

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 }
多想一想

 

posted @ 2019-03-12 12:19  新之守护者  阅读(178)  评论(0编辑  收藏  举报