题目连接: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. 2018-2019-2 20165325 网络对抗技术 Exp4 恶意代码分析

    2018-2019-2 20165325 网络对抗技术 Exp4 恶意代码分析 实验内容(概要) 一.系统(联网)运行监控 1. 使用如计划任务,每隔一分钟记录自己的电脑有哪些程序在联网,逐步排查并且 ...

  2. Qt for Android开发总结

    近段时间,本人使用Qt5.3.0开发了Android应用,由于官方资料较少,在此记录开发过程遇到的问题及解决方法 1.Android平台的视频播放,只能使用qml的MediaPlayer 2.qml中 ...

  3. Webpack自动化工程

    近几年,前端各种框架工具层出不穷,从两三年前还是一个jQuery搞定全站,到之后requirejs/seajs,node,gulp/webpack,Angular/React/Vue,RN/weex的 ...

  4. 【python】面向对象编程之@property、@setter、@getter、@deleter用法

    @property装饰器作用:把一个方法变成属性调用 使用@property可以实现将类方法转换为只读属性,同时可以自定义setter.getter.deleter方法 @property&@ ...

  5. 浅谈《Linux就该这么学》

    就在去年十月份的时候,偶尔在Linux技术群了看到别人分享的<Linux就该这么学>,好奇的就点进去看看,当时看完首页,突然发现刘遄老师说到心坎里去了,于是就仔细看了看红帽认证的讲解以及后 ...

  6. 基于Https协议返回Jason字符串

    一:代码结构 二:框架结果: spring+springMvc+springJdbc 三:源代码 1:Ctrl 层 package com.todaytech.yth.gdsd.base.DataIn ...

  7. VS Code 1.28版本设置中文界面的方法

    最近将vscode升级到1.28版本,发现升级后默认界面变成英文了,而且在按照网上的说法在locale.json设置locale: "zh-cn"也不起效,解决的解决方法很简单: ...

  8. 在SOUI中使用窗口自適應大小

    SOUI 2.5.0.3開始支持窗口大小自適應. 2.5.0.3以前,宿主窗口要適應顯示內容大小比較麻煩,因爲一般都是佈局內容適應宿主. SOUI 2.5.+開始支持線性佈局,線性佈局是借鑑的Andr ...

  9. 如何明确区分代码中的1和l

    如poly1d 单独将其复制到记事本,然后按ctrl+F,输入要查找的对象,数字1或者小写字母l,找到的对象会已高亮表示,所以就可以确定了高亮表示的是数字1还是字母l.

  10. Ubuntu安装Hadoop

    系统:Ubuntu16.04 JDK:jdk-8u201 Hadoop:3.1.2 一.安装JDK https://www.cnblogs.com/tanrong/p/10641803.html 二. ...