Justified Jungle Gym - 101620J dfs

题意: 给定一颗树, 问删除几条边可以使每个连通块内的个数都相同,输出合法的可删除的边数。

日常统计子树大小,顺便标一下。

如果我要统计每个块中点的个数是x的话  我需要统计块中点的个数是x的个数,我就需要统计 k*x (k *x<= n)出现的次数。

至于为什么,画个树形图感受一下吧
 

#include <bits/stdc++.h>
#define ms(x) memset(x, 0, sizeof(x))
#define ll long long
using namespace std;

const int N = 1000000 + 10, M = 1000000 + 10, INF = 0x3f3f3f3f;
struct node{
    int v;
    node(int x):v(x){}
};
vector<node>E[N];
void addedge(int u, int v){
    E[u].push_back(v);
    E[v].push_back(u);
}
int n, m;
int q[N];
int in[N];
int dfs(int fa, int x){
    q[x] = 1;
    for(int i=0;i<E[x].size();i++){
        int v = E[x][i].v;
        if(v == fa) continue;
        q[x] = q[x] + dfs(x, v);
    }
    in[q[x]]++;
    return q[x];
}
bool check(int x){
    int sum = 0;
    for(int i=x;i<=n;i+=x){
        sum += in[i];
    }
//    if(sum == n/x) return 1
    return sum==(n/x);
}
int main()
{
    ms(in);
    scanf("%d", &n);
    for(int i=0;i<n-1;i++){
        int u, v;
        scanf("%d%d",&u,&v);
        addedge(u, v);
    }
    dfs(-1, 1);
    vector<int>ans;
    ans.push_back(n-1);
    for(int i=2;i<=(int)sqrt(n);i++){
        if(n%i==0){
            if(check(i))
                ans.push_back(n/i - 1);
            if(check(n/i))
                ans.push_back(i-1);
        }
    }
    sort(ans.begin(), ans.end());
    for(int i=0;i<ans.size();i++){
        if( i) printf(" ");
        printf("%d",ans[i]);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值