2017 CERC

https://codeforces.com/gym/101620/

解题报告:https://www.cnblogs.com/GerynOhenz/p/8418171.html

Problem J:Justified Jungle

题目描述:给定一个有n

个节点的数,找出所有的整数k,满足在树上删掉k

条边后,形成的每棵树的节点数相同。

solution
首先,k+1

一定是n的因数。随意找一个点做根,求出每棵子树的大小。如果某一个k是答案,则子树大小是n/k+1的倍数的个数应该是k+1

。可以证明这是充要条件。

时间复杂度:O(nlogn)

证明的思路:我个人感觉是这样,每次把最下面的是n/k+1的倍数的子树找出来,割掉它,然后它的父亲大小仍然是n/k+1的倍数,重复操作,直到分割完为止。

代码:

#include
using namespace std;
const int maxn=1e6+7;
struct edge{
    int to;
    int next;
};
int n,size[maxn],vis[maxn]={0};

vector e[maxn];

void add_edge(int u,int v){
    e[u].push_back(v);
    e[v].push_back(u);
}

void build(int x,int pre){
    size[x]=1;
    for (auto it:e[x]){
        if (it!=pre){
            build(it,x);
            size[x]+=size[it];
        }
    }
    vis[size[x]]++;
}

bool check(int k){
    if (n%(k+1)) return 0;
    int s=n/(k+1),num=0;
    for (int i=s; i<=n; i+=s){
        num+=vis[i];
    }
    return num==(k+1);
}

int main(){
    scanf("%d",&n);
    int x,y;
    for (int i=0; i

 

你可能感兴趣的:(队切训练)