Description

Sherco是一位经验丰富的魔♂法师。
Sherco在第零次圣杯战争中取得了胜利,并取得了王之宝藏——王の树。
他想把这棵树砍去任意条边,拆成若干棵新树,并装饰在他的摩托上,让他的摩托更加酷炫。
但Sherco认为,这样生成的树不具有美感,于是Sherco想让每棵新树的节点数相同。
他想知道有多少种方法分割这棵树。

Input

第一行一个正整数N,表示这棵树的结点总数。
接下来N-1行,每行两个数字X,Y表示编号为X的结点与编号为Y的结点相连。结点编号的范围为[1,N]。

Output

一个整数,表示方案数。注意,不砍去任何一条边也算作一种方案。

Sample Input

6
1 2
2 3
2 4
4 5
5 6

Sample Output

3

Data Constraint

对于40%的数据,N ≤ 15
对于60%的数据,N ≤ 10^5
对于100%的数据,N ≤ 10^6
数据规模非常大,请使用高效的读入方式。
 
做法:强行选定一个根,然后求出每个节点size的大小,当新子树大小确定时,只有一种方案,所以我们可以枚举新子树大小k,当所有节点中size值是k的倍数的节点数为n/k时,方案合法。
 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #define N 1000007
 5 using namespace std;
 6 int n,tot,list[N],size[N],fa[N],b[N],ans,ls[N];
 7 struct edge{
 8     int to,next;
 9 }e[N*2];
10 bool v[N];
11     
12 inline int Read(){
13     int s=0;
14     char ch=getchar();
15     for(;ch<'0'||ch>'9';ch=getchar());
16     for(;ch>='0'&&ch<='9';s=s*10+ch-'0',ch=getchar());
17     return s;
18 }
19 
20 inline void Add(int x,int y){
21     e[++tot].to=y;
22     e[tot].next=ls[x];
23     ls[x]=tot;
24 }
25 
26 void Init(){
27     n=Read();
28     for (int i=1;i<n;i++){
29         int x=Read(),y=Read();
30         Add(x,y),Add(y,x);
31     }
32 }
33 
34 void Bfs(){
35     int h=0,t=0;
36     list[++t]=1;
37     v[1]=1;
38     for(;h<t;){
39         h++;
40         int now=list[h];
41         for (int i=ls[now];i;i=e[i].next){
42             if (v[e[i].to]) continue;
43             fa[e[i].to]=now;
44             list[++t]=e[i].to;
45             v[e[i].to]=1;
46         }
47     }
48 }
49 
50 void Calc_son(){
51     for (int i=1;i<=n;i++) size[i]=1;
52     for (int i=n;i>=1;i--) size[fa[list[i]]]+=size[list[i]];
53     for (int i=1;i<=n;i++) b[size[i]]++;
54 }
55 
56 int main(){
57     Init();
58     Bfs();
59     Calc_son();
60     for (int i=1;i<=n;i++){
61         if (n%i) continue;
62         int k=0;
63         for (int j=1;j<=n/i;j++)
64             k+=b[i*j];
65         if (k==n/i) ans++;
66     }
67     printf("%d",ans);
68 }
View Code