【BZOJ3162】独钓寒江雪 树同构+DP
【BZOJ3162】独钓寒江雪



题解:先进行树hash,方法是找重心,如果重心有两个,则新建一个虚点将两个重心连起来,新点即为新树的重心。将重心当做根进行hash,hash函数不能太简单,我的方法是:将x的所有儿子的hash值排序,然后将这些hash值立方合在一起作为x的hash值。
进行完树hash后,我们考虑DP。首先不考虑同构,设f[0/1][x]表示选(不选)x时,在x的子树中选出独立集的方案数,则有
$f[0][x]=\prod f[1][y]+f[0][y]\\f[1][x]=\prod f[0][y]$
考虑同构,如果x有m个儿子是相同的,它们的f值都是s,那么可以转化成如下问题:给m个相同球染s种颜色有多少种方案,显然答案=$C_{m+s-1}^m$。
如果根是虚点,那么最后统计答案的时候需要特判。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxn=500010;
const ll mod=1000000007;
int n,rt,rt1,rt2,cnt;
int head[maxn],next[maxn<<1],to[maxn<<1],siz[maxn];
bool vis[maxn];
ull hs[maxn];
ll f[2][maxn],ine[maxn],jcc[maxn];
vector<int> ch[maxn];
bool cmp(int a,int b)
{
return hs[a]<hs[b];
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
void findr(int x,int fa)
{
siz[x]=1;
int flag=0;
for(int i=head[x];i!=-1;i=next[i]) if(to[i]!=fa) findr(to[i],x),siz[x]+=siz[to[i]],flag|=(siz[to[i]]>(n/2));
flag|=(n-siz[x]>(n/2));
if(!flag&&rt1) rt2=x;
if(!flag&&!rt1) rt1=x;
}
void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
void gethash(int x)
{
for(int i=head[x];i!=-1;i=next[i]) if(!vis[to[i]]) vis[to[i]]=1,ch[x].push_back(to[i]);
hs[x]=ch[x].size()+1;
if(!ch[x].size()) return ;
for(int i=0;i<(int)ch[x].size();i++) gethash(ch[x][i]);
sort(ch[x].begin(),ch[x].end(),cmp);
for(int i=0;i<(int)ch[x].size();i++) hs[x]=hs[x]*131+hs[ch[x][i]]*hs[ch[x][i]]*hs[ch[x][i]];
}
ll calc(ll a,ll b)
{
ll ret=1;
for(ll i=a;i>a-b;i--) ret=ret*i%mod;
return ret*jcc[b]%mod;
}
void dfs(int x)
{
f[0][x]=1,f[1][x]=1;
ll now=0;
for(int i=0,j;i<(int)ch[x].size();i++)
{
j=ch[x][i],dfs(j);
now++;
if(i==(int)ch[x].size()-1||hs[j]!=hs[ch[x][i+1]])
{
f[0][x]=f[0][x]*calc(now+f[1][j]+f[0][j]-1,now)%mod;
f[1][x]=f[1][x]*calc(now+f[0][j]-1,now)%mod;
now=0;
}
}
}
int main()
{
n=rd();
int i,a,b;
memset(head,-1,sizeof(head));
ine[1]=jcc[1]=1;
for(i=2;i<=n;i++) ine[i]=(mod-(mod/i)*ine[mod%i]%mod)%mod,jcc[i]=jcc[i-1]*ine[i]%mod;
for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
findr(1,0);
if(rt2) add(++n,rt1),add(n,rt2),rt=n;
else rt=rt1;
vis[rt]=1,gethash(rt);
dfs(rt);
if(rt2)
{
if(hs[rt1]==hs[rt2]) printf("%lld",(f[0][rt1]*(f[0][rt1]+1)/2+f[0][rt1]*f[1][rt2])%mod);
else printf("%lld",(f[0][rt]-f[1][rt1]*f[1][rt2]%mod+mod)%mod);
}
else printf("%lld",(f[0][rt]+f[1][rt])%mod);
return 0;
}
【BZOJ3162】独钓寒江雪 树同构+DP的更多相关文章
- BZOJ 3162 / Luogu P4895: 独钓寒江雪 树hash+DP
题意 给出一棵无根树,求本质不同的独立集数模100000000710000000071000000007的值. n≤500000n\le 500000n≤500000 题解 如果是有根树就好做多了.然 ...
- 『Andrew and Chemistry 树同构』
Andrew and Chemistry Description During the chemistry lesson Andrew learned that the saturated hydro ...
- 【BZOJ-3572】世界树 虚树 + 树形DP
3572: [Hnoi2014]世界树 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1084 Solved: 611[Submit][Status ...
- 【BZOJ-2286】消耗战 虚树 + 树形DP
2286: [Sdoi2011消耗战 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 2120 Solved: 752[Submit][Status] ...
- 树状DP (poj 2342)
题目:Anniversary party 题意:给出N各节点的快乐指数,以及父子关系,求最大快乐指数和(没人职员愿意跟直接上司一起玩): 思路:从底向上的树状DP: 第一种情况:第i个员工不参与,F[ ...
- POJ3659 Cell Phone Network(树上最小支配集:树型DP)
题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. ...
- bzoj 2286 [Sdoi2011]消耗战(虚树+树上DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2286 [题意] 给定一棵树,切断一条树边代价为ci,有m个询问,每次问使得1号点与查询 ...
- uva12489 Combating cancer(树同构)
转载请注明出处: http://www.cnblogs.com/fraud/ ——by fraud https://uva.onlinejudge.org/index.php?opt ...
- poj3659树状DP
Cell Phone Network Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6273 Accepted: 225 ...
随机推荐
- 莫比乌斯函数之和(51nod 1244)
莫比乌斯函数,由德国数学家和天文学家莫比乌斯提出.梅滕斯(Mertens)首先使用μ(n)(miu(n))作为莫比乌斯函数的记号.具体定义如下: 如果一个数包含平方因子,那么miu(n) = 0.例如 ...
- cogs2060 除法表达式
http://blog.csdn.net/sdfzyhx/article/details/52254071 作为分母的数当然是越少越好.将x2作为分母,其他作为分子,不断约分,最后判断. /*by S ...
- 获取本机外网IP的工具类
ExternalIpAddressFetcher.java package com.tyust.common; import java.io.IOException; import java.io.I ...
- NoSQL数据库 Couchbase Server - 分布式缓存
Couchbase Server (前身是 Membase) 是一个分布式的面向文档的 NoSQL 数据库管理系统,该系统联合了 CouchDB 的简单和可靠以及 Memcached 的高性能以及 M ...
- python笔记2:函数
5. 函数 Python函数代码块以 def 关键词开头; 函数内容以冒号起始,并且缩进. *注: python中,strings, tuples, 和 numbers 是不可更改的对象,而 list ...
- rsync数据同步工具应用指南
Rsync (Remote synchonization) rsync是Unix下的一款应用软件,它能同步更新两处计算机的文件与目录,并适当利用差分编码以减少数据传输.rsync中一项与其他大部分类 ...
- Ubuntu 16.04下安装WineHQ
说明: 1.Wine和WIneHQ没什么区别,新版和旧版的问题. 2.安装了深度的Wine包也可以和WineHQ一起兼容,因为深度的应用名已经加了deepin前缀,所以不冲突. 3.安装了Wine之后 ...
- ubuntu配置django
安装 安装Apache sudo apt-get install apache2 安装Django 下载Django 安装mod_wsgi sudo apt-get install libapache ...
- 3.环境搭建-Hadoop(CDH)集群搭建
目录 目录 实验环境 安装 Hadoop 配置文件 在另外两台虚拟机上搭建hadoop 启动hdfs集群 启动yarn集群 本文主要是在上节CentOS集群基础上搭建Hadoop集群. 实验环境 Ha ...
- 现代数字信号处理——AR模型
1. AR模型概念观 AR模型是一种线性预测,即已知N个数据,可由模型推出第N点前面或后面的数据(设推出P点),所以其本质类似于插值,其目的都是为了增加有效数据,只是AR模型是由N点递推, ...