1. 程式人生 > >【bzoj4401】塊的計數(水dfs)

【bzoj4401】塊的計數(水dfs)

har map 根節點 pro include nbsp print click blank

  題目傳送門: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)