标签:pre opened ons push size sort code closed splay
题意:
给出一棵树,删掉其中一些边,要求生成的每个子树节点数一样。输出所有可以删掉的边数。
题解:
以节点1为根,预处理每个子树的大小。对于每个n的因数x,还需满足子树为他倍数的点够n/x个,那么删的边数就为n/x-1。
#include <bits/stdc++.h> using namespace std; const int N = 1e6+10; int n; int u, v; int sz[N], vis[N]; int tot; int head[N], point[N<<1], nxt[N<<1]; vector<int> ans; void add_edge(int u, int v) { point[++tot] = v; nxt[tot] = head[u]; head[u] = tot; } void dfs(int u, int pre) { sz[u] = 1; for(int i = head[u]; i; i = nxt[i]) { if(point[i]==pre) continue; dfs(point[i], u); sz[u] += sz[point[i]]; } vis[sz[u]]++; } bool check(int x) { int cnt = 0; for(int i = x; i <= n; i+=x) cnt += vis[i]; return cnt==n/x; } int main() { scanf("%d", &n); ans.push_back(n-1); for(int i = 1; i < n; i++) { scanf("%d%d", &u, &v); add_edge(u, v); add_edge(v, u); } dfs(1, 0); int up = sqrt(n); for(int i = 2; i <= up; i++) { if(!(n % i)) { if(check(i)) ans.push_back(n/i-1); if(i*i!=n && check(n/i)) ans.push_back(i-1); } } sort(ans.begin(), ans.end()); int len = ans.size(); for(int i = 0; i < len; i++) { printf("%d", ans[i]); if(i!=len-1) printf(" "); } }
GYM - 101620 J.Justified Jungle
标签:pre opened ons push size sort code closed splay
原文地址:https://www.cnblogs.com/Pneuis/p/9029274.html