Educational Codeforces Round 17F Tree nesting

时间:2022-09-13 12:42:42

来自FallDream的博客,未经允许,请勿转载, 谢谢。


给你两棵树,一棵比较大(n<=1000),一棵比较小(m<=12) 问第一棵树中有多少个连通子树和第二棵同构。

答案取膜1e9+7

考虑在大树中随便选个根,然后在小的那棵那里枚举一个根作为大树中深度最小的节点(注意哈希判同构)

然后f[x][y]表示大树的x节点作为小树的y节点的方案数。

如果y是叶子结点,f[x][y]=1

否则要用x的儿子中的一些节点表示y的所有叶子节点。

考虑一个状压dp,g[i][s]表示前i个儿子表示了小树的s集合内的节点的方案数,容易转移。

然后如果y有一些儿子同构,则需要除以个数的阶乘。

复杂度上界是n*m*2^m

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<map>
#define MN 1000
#define mod 1000000007
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
unsigned long long ha[MN+];vector<unsigned long long> v[MN+];map<unsigned long long,int> mp,mp2;
int n,m,head[MN+],Head[MN+],fa[MN+],cnt=,f[MN+][],F[<<],size[MN+],son[MN+],q[MN+],ans=,now,P[];
struct edge{int to,next;}e[MN*+];
inline void R(int&x,int y){x+=y;x>=mod?x-=mod:;}
inline void ins(int*H,int f,int t)
{
e[++cnt]=(edge){t,H[f]};H[f]=cnt;
e[++cnt]=(edge){f,H[t]};H[t]=cnt;
} int pow(int x,int k)
{
int sum=;
for(;k;k>>=,x=1LL*x*x%mod)
if(k&) sum=1LL*sum*x%mod;
return sum;
} void GetHa(int x,int f)
{
ha[x]=;size[x]=;v[x].clear();fa[x]=f;
for(int i=Head[x];i;i=e[i].next)
if(e[i].to!=f)
{
GetHa(e[i].to,x);
v[x].push_back(ha[e[i].to]);
}
son[x]=v[x].size();
sort(v[x].begin(),v[x].end());
for(int i=;i<v[x].size();++i) ha[x]=ha[x]*+v[x][i];
ha[x]=ha[x]*+size[x];
} void Solve(int x,int fat)
{
int num=;
for(int i=head[x];i;i=e[i].next)
if(e[i].to!=fat) Solve(e[i].to,x),++num;
for(int i=;i<=m;++i)
{
if(!son[i]){f[x][i]=;continue;}
if(num<son[i]){f[x][i]=;continue;}
for(int k=;k<<<son[i];++k)F[k]=;
F[]=;int top=;
for(int j=Head[i];j;j=e[j].next) if(e[j].to!=fa[i]) q[++top]=e[j].to,++mp2[ha[e[j].to]];
for(int j=head[x];j;j=e[j].next)
if(e[j].to!=fat)
{
for(int s=(<<top)-;~s;--s)
for(int k=;k<=top;++k) if(f[e[j].to][q[k]])
if(!(s&(<<k-))) R(F[s|(<<k-)],1LL*F[s]*f[e[j].to][q[k]]%mod);
}
f[x][i]=F[(<<top)-];
for(int j=;j<=top;++j)
if(mp2[ha[q[j]]]) f[x][i]=1LL*f[x][i]*pow(P[mp2[ha[q[j]]]],mod-)%mod,mp2[ha[q[j]]]=;
}
R(ans,f[x][now]);
} int main()
{
n=read();P[]=;
for(int i=;i<=;++i) P[i]=1LL*P[i-]*i%mod;
for(int i=;i<n;++i) ins(head,read(),read());m=read();
for(int i=;i<m;++i) ins(Head,read(),read());
for(int i=;i<=m;++i)
{
GetHa(i,);
if(mp[ha[i]]) continue;
memset(f,,sizeof(f));mp[ha[i]]=;
now=i;Solve(,);
}
printf("%d\n",ans);
return ;
}

Educational Codeforces Round 17F Tree nesting的更多相关文章

  1. Educational Codeforces Round 17

    Educational Codeforces Round 17 A. k-th divisor 水题,把所有因子找出来排序然后找第\(k\)大 view code //#pragma GCC opti ...

  2. Educational Codeforces Round 35 &lpar;Rated for Div&period; 2&rpar;

    Educational Codeforces Round 35 (Rated for Div. 2) https://codeforces.com/contest/911 A 模拟 #include& ...

  3. Educational Codeforces Round 67

    Educational Codeforces Round 67 CF1187B Letters Shop 二分 https://codeforces.com/contest/1187/submissi ...

  4. Educational Codeforces Round 41 967 E&period; Tufurama &lpar;CDQ分治 求 二维点数&rpar;

    Educational Codeforces Round 41 (Rated for Div. 2) E. Tufurama (CDQ分治 求 二维点数) time limit per test 2 ...

  5. &lbrack;Educational Codeforces Round 16&rsqb;E&period; Generate a String

    [Educational Codeforces Round 16]E. Generate a String 试题描述 zscoder wants to generate an input file f ...

  6. &lbrack;Educational Codeforces Round 16&rsqb;D&period; Two Arithmetic Progressions

    [Educational Codeforces Round 16]D. Two Arithmetic Progressions 试题描述 You are given two arithmetic pr ...

  7. &lbrack;Educational Codeforces Round 16&rsqb;C&period; Magic Odd Square

    [Educational Codeforces Round 16]C. Magic Odd Square 试题描述 Find an n × n matrix with different number ...

  8. &lbrack;Educational Codeforces Round 16&rsqb;B&period; Optimal Point on a Line

    [Educational Codeforces Round 16]B. Optimal Point on a Line 试题描述 You are given n points on a line wi ...

  9. &lbrack;Educational Codeforces Round 16&rsqb;A&period; King Moves

    [Educational Codeforces Round 16]A. King Moves 试题描述 The only king stands on the standard chess board ...

随机推荐

  1. HTML基础2 表单和框架

    表单: <form id="" name="" method="post/get" action"负责处理的服务端&quot ...

  2. 20145211 《Java程序设计》第8周学习总结——自在飞花轻似梦

    教材学习内容总结 认识NIO Java NIO(New Input/Output)--新的输入/输出API包--是2002年引入到J2SE 1.4里的.Java NIO的目标是提高Java平台上的I/ ...

  3. android设备的vpn功能

    VPN是什么? VPN:Virtual Private Network,虚拟专用网络:是通过私有的隧道技术在公共数据网络上仿真一条点到点的专线技术,其实质上就是利用加密技术在公网上封装出一个数据通讯隧 ...

  4. Dockerfile 中的 CMD 与 ENTRYPOINT

    CMD 和 ENTRYPOINT 指令都是用来指定容器启动时运行的命令.单从功能上来看,这两个命令几乎是重复的.单独使用其中的一个就可以实现绝大多数的用例.但是既然 doker 同时提供了它们,为了在 ...

  5. MySQL服务安全加固

    数据库管理人员可以参考本文档进行 MySQL 数据库系统的安全配置加固,提高数据库的安全性,确保数据库服务稳定.安全.可靠地运行. 漏洞发现 您可以使用安骑士企业版自动检测您的服务器上是否存在 MyS ...

  6. Sql Server数据库之identity&lpar;自增&rpar;

    一.identity的基本用法 1.identity的含义: identity表示该字段的值会自动更新,通常情况下,不允许直接修改identity修饰的字段,否则编译会报错 2.基本语法 列名  数据 ...

  7. 树莓派&plus;tomcat&plus;mysql安装及配置

    0x00 系统:ubuntu-mate-16.04.2-desktop-armhf-raspberry-pi 该版本中apt源在国内访问速度不算慢,可以不换,但软件包不完整,建议添加阿里云源 deb ...

  8. CSS——超链接颜色设置

    <!-- 链接颜色 --> a:link { color:#FF0000; text-decoration:underline; } a:visited { color:#00FF00; ...

  9. Debian 无线网卡驱动问题

    参考这里:https://wiki.debian.org/iwlwifi Debian 9 "Stretch" Add a "non-free" compone ...

  10. java判断给定路径或URL下的文件或文件夹是否存在?

    if (file.exists()) { 来判断这是不是一个文件. file.isDirectory() 来判断这是不是一个文件夹. 1.File testFile = new File(testFi ...