Problem J: Justified Jungle

Time limit: 6 s Memory l

imit: 512 MiB

As you probably know, a tree is a graph consisting of n nodes and n−1 undirected edges in which any two nodes are connected by exactly one path. A forest is a graph consisting of one or more trees. In other words, a graph is a forest if every connected component is a tree. A forest is justified if all connected components have the same number of nodes. Given a tree G consisting of n nodes, find all positive integers k such that a justified forest can be obtained by erasing exactly k edges from G. Note that erasing an edge never erases any nodes. In particular when we erase all n−1 edges from G, we obtain a justified forest consisting of n one-node components.
Input The first line contains an integer n (2≤ n ≤1000000) — the number of nodes in G. The k-th of the following n−1 lines contains two different integers ak and bk (1≤ ak,bk ≤n) — the endpoints of the k-th edge.
Output
The first line should contain all wanted integers k, in increasing order.
Example
input
8 1 2 2 3 1 4 4 5 6 7 8 3 7 3
output
1 3 7
Figures depict justified forests obtained by erasing 1, 3 and 7 edges from the tree in the example input.

 

 1 // 题目大意:删去k条边,树变为相等个点的连通分量,求所有正整数k。
 2 
 3 #include<bits/stdc++.h>
 4 using namespace std;
 5 typedef long long ll;
 6 #define maxn 1000006
 7 int head[maxn],cnt,siz[maxn],v[maxn],n;
 8 struct edge{
 9     int to,nxt;
10 }e[maxn<<1];
11 void add_edge(int u,int v){
12     e[cnt].to=v;
13     e[cnt].nxt=head[u];
14     head[u]=cnt++;
15 }
16 void dfs(int u,int fa){
17     siz[u]=1;
18     for(int i=head[u];i!=-1;i=e[i].nxt){
19         int v=e[i].to;
20         if(v==fa) continue;
21         dfs(v,u);
22         siz[u]+=siz[v];
23     }
24     v[siz[u]]++; 
25 }
26 bool check(int x){
27     x++;
28     if(n%x) return 0;
29     int w=n/x,sum=0;
30     for(int i=w;i<=n;i+=w) sum+=v[i];
31     return sum==x;
32 }
33 int main(){
34     memset(head,-1,sizeof head);
35     scanf("%d",&n);
36     for(int i=0;i<n-1;i++){
37         int a,b;
38         scanf("%d%d",&a,&b);
39         add_edge(a,b);
40         add_edge(b,a);
41     }
42     dfs(1,-1);
43     for(int i=1;i<=n;i++){
44         if(check(i)) printf("%d ",i);
45     }
46     return 0;
47 }