题目连接:762F - Tree nesting

题目大意:给出两个树\(S,T\),问\(S\)中有多少连通子图与\(T\)同构。\(|S|\leq 1000,|T|\leq 12\)

题解:考虑树的最小表示法(有关知识可戳https://www.byvoid.com/zhs/blog/directed-tree-bracket-sequence),求出\(T\)以不同点为根时所有的子树状态

   开始对树\(S\)进行\(DFS\),求出每个点的状态为\(t\)时的方案数,由于\(t\)还是由\(n\)个数字(括号序列)合并起来的,而且\(n\)不会太大,所以可以用二进制DP求解

   对当前点求解时,只需遍历其儿子,将儿子的解并入当前的状态即可。由于一个点可能有若干个形状相同的子树,所以要考虑去重,具体实现见代码

#include<bits/stdc++.h>
using namespace std;
#define N 1001
#define M 1<<12
#define MOD 1000000007
int len(int x){return -__builtin_clz(x);}
int Union(int x,int y){return (x<<len(y))|y;}
struct Tree
{
int n,ans;
int f[M][];
vector<int>d[N];
map<int,int>num[N];
map<int,vector<int> >mp;
void read()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
d[u].push_back(v);
d[v].push_back(u);
}
}
int dfs(int cur,int pre)
{
int res=;
vector<int>tmp;
//tmp用来记录子树的状态
for(auto nxt:d[cur])if(nxt!=pre)
tmp.push_back(dfs(nxt,cur));
sort(tmp.begin(),tmp.end());
for(auto x:tmp)res=Union(res,x);
res<<=;
//res表示当前节点的最小表示
if(!mp.count(res))mp[res]=tmp;
//将当前点对应的子树们也记录下来
return res;
}
void getID()
{
for(int i=;i<=n;i++)
dfs(i,);
//枚举以所有的点为根的情况
}
void DP(int cur,int pre,const Tree &T)
{
for(auto nxt:d[cur])if(nxt!=pre)DP(nxt,cur,T);
for(const auto &pi:T.mp)//枚举T中的所有状态
{
auto &types=pi.second;
int id=pi.first,n=types.size(),now=,lst=;
for(int i=;i<(<<n);i++)f[i][]=f[i][]=;
f[][]=;
//id为当前枚举到的状态,n为当前状态拥有的子树数目,用滚动数组实现儿子们的合并
for(auto nxt:d[cur])if(nxt!=pre)
{
now^=,lst^=;
for(int i=;i<(<<n);i++)
f[i][now]=f[i][lst];
for(int i=;i<n;i++)
if(num[nxt][types[i]])//num[i][j]表示点i的状态为j时方案有多少个
for(int j=(<<n)-;j>=;j--)
if(f[j][lst] && !((<<i)&j) && !(i && types[i]==types[i-] && !((<<(i-))&j)))
// (i && types[i]==types[i-1] && !((1<<(i-1))&j)代表的是
//当前枚举的子树和前一个子树同构 ,且前一个子树的状态未记录
(f[(<<i)|j][now]+=1ll*f[j][lst]*num[nxt][types[i]]%MOD)%=MOD;
}
if(f[(<<n)-][now])
{
num[cur][id]=f[(<<n)-][now];//集齐了所有子树即为对应num的答案
if(len(id)==*T.n)(ans+=num[cur][id])%=MOD;//id的二进制长度为2m则说明一定是根节点的状态,加入答案
}
}
}
}S,T;
int main()
{
S.read();
T.read();
T.getID();
S.DP(,,T);
printf("%d\n",S.ans);
}

[Educational Round 17][Codeforces 762F. Tree nesting]的更多相关文章

  1. [Codeforces]762F - Tree nesting

    题目大意:给出一棵n个点的树和一棵m个点的树,问第一棵树有多少个连通子树与第二棵树同构.(n<=1000,m<=12) 做法:先找出第二棵树的重心(可能为边),以这个重心为根,可以避免重复 ...

  2. [Educational Round 3][Codeforces 609E. Minimum spanning tree for each edge]

    这题本来是想放在educational round 3的题解里的,但觉得很有意思就单独拿出来写了 题目链接:609E - Minimum spanning tree for each edge 题目大 ...

  3. [Educational Round 5][Codeforces 616F. Expensive Strings]

    这题调得我心疲力竭...Educational Round 5就过一段时间再发了_(:з」∠)_ 先后找了三份AC代码对拍,结果有两份都会在某些数据上出点问题...这场的数据有点水啊_(:з」∠)_[ ...

  4. [Educational Round 3][Codeforces 609F. Frogs and mosquitoes]

    这题拖了快一周_(:з」∠)_就把这货单独拿出来溜溜吧~ 本文归属:Educational Codeforces Round 3 题目链接:609F - Frogs and mosquitoes 题目 ...

  5. [Educational Round 13][Codeforces 678F. Lena and Queries]

    题目连接:678F - Lena and Queries 题目大意:要求对一个点集实现二维点对的插入,删除,以及询问\(q\):求\(max(x\cdot q+y)\) 题解:对每个点集内的点\(P( ...

  6. [Educational Round 10][Codeforces 652F. Ants on a Circle]

    题目连接:652F - Ants on a Circle 题目大意:\(n\)个蚂蚁在一个大小为\(m\)的圆上,每个蚂蚁有他的初始位置及初始面向,每个单位时间蚂蚁会朝着当前面向移动一个单位长度,在遇 ...

  7. [Educational Round 59][Codeforces 1107G. Vasya and Maximum Profit]

    咸鱼了好久...出来冒个泡_(:з」∠)_ 题目连接:1107G - Vasya and Maximum Profit 题目大意:给出\(n,a\)以及长度为\(n\)的数组\(c_i\)和长度为\( ...

  8. 【Henu ACM Round#17 E】Tree Construction

    [链接] 我是链接,点我呀:) [题意] 在这里输入题意 [题解] 做这题之前先要知道二叉排序树的一个性质. 就是它的中序遍历的结果就是这个数组升序排序. (且每个节点的左边的节点都是比这个节点的值小 ...

  9. Educational Codeforces Round 17

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

随机推荐

  1. Java继承详解

    目录 前言 继承的格式: 继承的特点: 继承的优缺点 继承的注意点(重要) 继承的使用 前言 类是对对象的抽象,具有共同属性和行为的许多对象抽象出一个类. 例如:有三个学生小明,小红,小李都有姓名,年 ...

  2. 【easy】746. Min Cost Climbing Stairs 动态规划

    On a staircase, the i-th step has some non-negative cost cost[i]assigned (0 indexed). Once you pay t ...

  3. web文件下载

    web页面实现文件下载的几种方法 今天碰到文件下载的一些问题,本着知其然也要知其所以然的精神,站在巨人的肩膀上深入学习和测试了一下,抛砖引玉,现在总结结论如下: 1)标准URL下载方式可以通过在web ...

  4. String,下表和切片,分割

    字符串介绍 1.字符串在内存中的存储 2.字符串的加法 3.字符串的格式化 1. 下标索引 所谓“下标”,就是编号,就好比超市中的存储柜的编号,通过这个编号就能找到相应的存储空间 字符串中" ...

  5. matplotlib 中的柱状图

    def drawBar(): pyplot.bar(range(5),[100,200,300,400,400]) pyplot.xticks(range(5),['A','B','C','D','E ...

  6. python3 函数注意要点

    一.定义一个函数: def test(): #用def关键词开头 print('*****') def test2(a,b): #a,b为形参 print(a,b) return a,b # retu ...

  7. set操作

    Set操作,Set集合就是不允许重复的列表 sadd(name,values) # name对应的集合中添加元素 scard(name) 获取name对应的集合中元素个数 sdiff(keys, *a ...

  8. Python+Flask搭建mock api server

    Python+Flask搭建mock api server 前言: 近期由于工作需要,需要一个Mock Server调用接口直接返回API结果: 假如可以先通过接口文档的定义,自己模拟出服务器返回结果 ...

  9. K3 WISE 开发插件《K3 WISE常用数据表整理》

    在后台数据库ICClassType表中,字段FID<0的是老单,FID>0的是新单. ----------------系统设置------------------------ FStatu ...

  10. 设置Jexus开机启动

    一.如需要开机没有登陆情况下就能运行的程序,存在系统服务(system)里,即:/lib/systemd/system/  ,服务以.service结尾 cd /lib/systemd/system/ ...