bzoj4401块的计数(水dfs)

Posted QuartZ_Z

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj4401块的计数(水dfs)相关的知识,希望对你有一定的参考价值。

  题目传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4401

  假设把树划分为x个节点作一块,那么显然只有当x|n的时候才可能存在划分方案,并且这种划分方案是唯一的。

  并且对于一棵树,只有当有n/x个节点的子树大小%x==0的时候才可能存在划分方案,因为如果把一棵树的根节点及其所在的块切掉,那么剩下的子树若存在划分方案,一定满足这些子树的节点个数%x==0。

  所以这道题就变成一道水题了。

  代码(我本来想着用bfs代替dfs会跑得快一点,然而似乎并没有什么卵用)

技术分享图片
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
#define ll long long
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
ll read()
{
    ll tmp=0; char f=1,c=getchar();
    while(c<0||9<c){if(c==-)f=-1; c=getchar();}
    while(0<=c&&c<=9){tmp=tmp*10+c-0; c=getchar();}
    return tmp*f;
}
using namespace std;
int size[1000010],q[1000010],fa[1000010],cnt[1000010];
int fir[1000010],ne[2000010],to[2000010];
int n,tot=0;
void add(int x,int y){to[++tot]=y; ne[tot]=fir[x]; fir[x]=tot;}
int main()
{
    int i;
    n=read();
    for(i=1;i<n;i++){
        int x=read(),y=read();
        add(x,y); add(y,x);
    }
    int h=1,t=1; q[1]=1; fa[1]=-1;
    while(h<=t){
        for(i=fir[q[h]];i;i=ne[i])
            if(!fa[to[i]])q[++t]=to[i],fa[to[i]]=q[h];
        ++h;
    }
    for(i=n;i;i--){
        size[q[i]]=1;
        for(int j=fir[q[i]];j;j=ne[j])
            if(to[j]!=fa[q[i]])size[q[i]]+=size[to[j]];
        ++cnt[size[q[i]]];
    }
    int ans=0;
    for(i=1;i<=n;i++)
        if(n%i==0){
            int tmp=0;
            for(int j=i;j<=n;j+=i)tmp+=cnt[j];
            if(tmp*i==n)++ans;
        }
    printf("%d\n",ans);
    return 0;
}
跑得慢也会输

 

  

以上是关于bzoj4401块的计数(水dfs)的主要内容,如果未能解决你的问题,请参考以下文章

bzoj 4401 块的计数 思想+模拟+贪心

bzoj 4401: 块的计数

bzoj4401块的计数 结论题

[BZOJ1501][NOI2005]智慧珠游戏

BZOJ.1016.[JSOI2008]最小生成树计数(Matrix Tree定理 Kruskal)

[bzoj3244] [洛谷P1232] [Noi2013] 树的计数