zoukankan      html  css  js  c++  java
  • 暑假考试题1:Count(树上拆分)

    题意:

    求一共有多少种方案可以把一棵树分成大小相同的几块。(即切掉一些边,使得每个连通块的点数相同)

    分析:

    枚举每一个数的因子,然后遍历整棵树,看是否可以划分,如果可以的话,ans+1(因为可以发现只有一种划分方法)。

    那么在遍历的时候怎么判断呢?

    从上向下求一遍siz,之后每一次检查now这个大小是否可以被划分时,再用dfs2从上向下dfs一遍,在回溯时将大于now的尽量减去。

    具体减的过程:

    当一个点的儿子v,siz[v]是大于now的话,说明减不掉了,即其儿子以下不能划分成大小相同的块,直接打标记一直返回。

    刚好等于,就剪掉儿子,并且改变u的siz大小(通过返回值传给深度较浅的节点)。

    小于,则说明可以积累到下一次再减,就不用管

    #include<bits/stdc++.h>
    using namespace std;
    #define N 1000005
    int tot=0,siz[N],to[N<<1],nex[N<<1],head[N],now,n,fl=0,tmp[N],ans=0;
    void add(int a,int b){ to[++tot]=b; nex[tot]=head[a]; head[a]=tot; }
    void dfs1(int u,int fa)
    {
        siz[u]=1;
        for(int i=head[u];i;i=nex[i]){
            int v=to[i];
            if(v==fa) continue;
            dfs1(v,u);
            siz[u]+=siz[v];
        }
    }
    int dfs2(int u,int fa)
    {
        if(fl) return 0;
        int flagg=0;
        tmp[u]=siz[u];
        for(int i=head[u];i;i=nex[i]){
            int v=to[i];
            if(v==fa) continue;
            int x=dfs2(v,u);
            if(fl) return 0;
            tmp[u]-=x;
            flagg+=x;
            if(tmp[v]==now) flagg+=now,tmp[v]=0,tmp[u]-=now;
            else if(tmp[v]>now) fl=1;
        }
        return flagg;
    }
    void solve(int x)
    {
        fl=0; now=x;
        dfs2(1,0);
        if(!fl) ans++;
    }
    int main()
    {
        freopen("count.in","r",stdin);
        freopen("count.out","w",stdout);
        int a,b;
        scanf("%d",&n);
        for(int i=1;i<=n-1;i++) scanf("%d%d",&a,&b),add(a,b),add(b,a);
        dfs1(1,0);
        int xx=sqrt(n);
        for(int i=1;i<=xx;i++)
        if(n%i==0){
            solve(i);
            if(n/i!=i) solve(n/i);
        } 
        printf("%d
    ",ans);
    }
    /*
    6
    1 2
    2 3
    2 4
    4 5
    5 6
    ans 3
    8
    1 2 
    1 7 
    1 8
    2 3
    2 4
    3 5
    3 6
    ans 2
    8
    1 2 
    1 7 
    2 3
    2 4
    3 5
    3 6
    5 9
    ans 4
    */
  • 相关阅读:
    最长回文字符(需要补)
    无重复字符的最长子串
    两数之和——链表
    两个数之和
    android 动画基础绘——帧动画(三)
    android 动画基础绘——view 动画(二)[补]
    android 动画基础绘——view 动画
    全国疫情精准定点动态更新(.net core)
    桶排序
    计数排序
  • 原文地址:https://www.cnblogs.com/mowanying/p/11396391.html
Copyright © 2011-2022 走看看