【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;
}
跑得慢也会输

 

  

posted @ 2018-01-01 20:59  QuartZ_Z  阅读(225)  评论(0编辑  收藏  举报