BZOJ4835 [Lydsy2017年4月月赛]遗忘之树

来源:互联网 发布:上海网站推广优化公司 编辑:程序博客网 时间:2024/05/21 15:50

f[x]表示分治树以x为根的子树的情况数

f[x]就等于对于每个分治儿子y,f[y]*siz[y]的乘积

但是注意到如果有两个重心他要求最小那个

所以如果有一个分治子树大小恰好等于本身子树大小/2,那么对于这个子树乘的就是f[y]*siz(y,x),siz(y,x)代表y的分治子树内标号比x大的点的个数

因为分支结构的树高是log的,所以sigma 子树大小也是log的(因为sigma 子树大小=sigma 点深度),所以暴力求siz(y,x)即可

#include<iostream>#include<cstring>#include<ctime>#include<cmath>#include<algorithm>#include<iomanip>#include<cstdlib>#include<cstdio>#include<map>#include<bitset>#include<set>#include<stack>#include<vector>#include<queue>using namespace std;#define MAXN 100010#define MAXM 1010#define ll long long#define eps 1e-8#define MOD 1000000007#define INF 1000000000struct vec{int to;int fro;};vec mp[MAXN];int tai[MAXN],cnt;bool cr[MAXN];int n;ll f[MAXN],siz[MAXN];int mn[MAXN];inline void be(int x,int y){mp[++cnt].to=y;mp[cnt].fro=tai[x];tai[x]=cnt;}int count(int x,int lim){int i,y;int re=0;if(x>lim){re++;}for(i=tai[x];i;i=mp[i].fro){y=mp[i].to;re+=count(y,lim);}return re;}void dfs(int x){int i,y;f[x]=siz[x]=1;mn[x]=x;for(i=tai[x];i;i=mp[i].fro){y=mp[i].to;dfs(y);siz[x]+=siz[y];mn[x]=min(mn[x],mn[y]);}for(i=tai[x];i;i=mp[i].fro){y=mp[i].to;if((siz[x]&1^1)&&(siz[y]==siz[x]>>1)){(f[x]*=f[y]*count(y,x)%MOD)%=MOD;}else{(f[x]*=f[y]*siz[y]%MOD)%=MOD;}}}int main(){int i,x,y;int tmp;scanf("%d",&tmp);while(tmp--){scanf("%d%*d",&n);cnt=0;for(i=1;i<=n;i++){tai[i]=0;cr[i]=1;}for(i=1;i<n;i++){scanf("%d%d",&x,&y);cr[y]=0;be(x,y);}for(i=1;i<=n;i++){if(cr[i]){dfs(i);printf("%lld\n",f[i]);break;}}}return 0;}/*16 53 44 53 66 11 2*/


0 0
原创粉丝点击