题目连接: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求解

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

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define N 1001
  4. #define M 1<<12
  5. #define MOD 1000000007
  6. int len(int x){return -__builtin_clz(x);}
  7. int Union(int x,int y){return (x<<len(y))|y;}
  8. struct Tree
  9. {
  10. int n,ans;
  11. int f[M][];
  12. vector<int>d[N];
  13. map<int,int>num[N];
  14. map<int,vector<int> >mp;
  15. void read()
  16. {
  17. scanf("%d",&n);
  18. for(int i=;i<=n;i++)
  19. {
  20. int u,v;
  21. scanf("%d%d",&u,&v);
  22. d[u].push_back(v);
  23. d[v].push_back(u);
  24. }
  25. }
  26. int dfs(int cur,int pre)
  27. {
  28. int res=;
  29. vector<int>tmp;
  30. //tmp用来记录子树的状态
  31. for(auto nxt:d[cur])if(nxt!=pre)
  32. tmp.push_back(dfs(nxt,cur));
  33. sort(tmp.begin(),tmp.end());
  34. for(auto x:tmp)res=Union(res,x);
  35. res<<=;
  36. //res表示当前节点的最小表示
  37. if(!mp.count(res))mp[res]=tmp;
  38. //将当前点对应的子树们也记录下来
  39. return res;
  40. }
  41. void getID()
  42. {
  43. for(int i=;i<=n;i++)
  44. dfs(i,);
  45. //枚举以所有的点为根的情况
  46. }
  47. void DP(int cur,int pre,const Tree &T)
  48. {
  49. for(auto nxt:d[cur])if(nxt!=pre)DP(nxt,cur,T);
  50. for(const auto &pi:T.mp)//枚举T中的所有状态
  51. {
  52. auto &types=pi.second;
  53. int id=pi.first,n=types.size(),now=,lst=;
  54. for(int i=;i<(<<n);i++)f[i][]=f[i][]=;
  55. f[][]=;
  56. //id为当前枚举到的状态,n为当前状态拥有的子树数目,用滚动数组实现儿子们的合并
  57. for(auto nxt:d[cur])if(nxt!=pre)
  58. {
  59. now^=,lst^=;
  60. for(int i=;i<(<<n);i++)
  61. f[i][now]=f[i][lst];
  62. for(int i=;i<n;i++)
  63. if(num[nxt][types[i]])//num[i][j]表示点i的状态为j时方案有多少个
  64. for(int j=(<<n)-;j>=;j--)
  65. if(f[j][lst] && !((<<i)&j) && !(i && types[i]==types[i-] && !((<<(i-))&j)))
  66. // (i && types[i]==types[i-1] && !((1<<(i-1))&j)代表的是
  67. //当前枚举的子树和前一个子树同构 ,且前一个子树的状态未记录
  68. (f[(<<i)|j][now]+=1ll*f[j][lst]*num[nxt][types[i]]%MOD)%=MOD;
  69. }
  70. if(f[(<<n)-][now])
  71. {
  72. num[cur][id]=f[(<<n)-][now];//集齐了所有子树即为对应num的答案
  73. if(len(id)==*T.n)(ans+=num[cur][id])%=MOD;//id的二进制长度为2m则说明一定是根节点的状态,加入答案
  74. }
  75. }
  76. }
  77. }S,T;
  78. int main()
  79. {
  80. S.read();
  81. T.read();
  82. T.getID();
  83. S.DP(,,T);
  84. printf("%d\n",S.ans);
  85. }

[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. VS Code保存使用项目Eslint规则格式化代码

    One.文件-首选项-设置-选择项目                  Two.打开右上角JSON设置            Three. 插入以下代码 { "eslint.options& ...

  2. 基于Spring Security OAuth2搭建的Spring Cloud 认证中心

    Github传送门:https://github.com/13babybear/bounter-springcloud 实现功能有: 整合JWT 刷新Token 自定义客户端储存 自定义用户储存 资源 ...

  3. web开发-前后端分离原理

    前言 前后端分离已成为互联网项目开发的业界标准使用方式,通过Nginx+Tomcat的方式(也可以中间加一个Node.js)有效的进行解耦,并且前后端分离会为以后的大型分布式架构.弹性计算架构.微服务 ...

  4. 4327: JSOI2012 玄武密码

    4327: JSOI2012 玄武密码 Description 在美丽的玄武湖畔,鸡鸣寺边,鸡笼山前,有一块富饶而秀美的土地,人们唤作进香河.相传一日,一缕紫气从天而至,只一瞬间便消失在了进香河中.老 ...

  5. C# 高级编程05----常用修饰符

    常用修饰符: 1.访问可见性修饰符 修饰符 应用于 说明 public 类型或成员 任何代码都可访问 protected 类型或内嵌类型的成员 只有子类能访问 internal 类型或成员 只能在包含 ...

  6. 论文阅读笔记四十八:Bounding Box Regression with Uncertainty for Accurate Object Detection(CVPR2019)

    论文原址:https://arxiv.org/pdf/1809.08545.pdf github:https://github.com/yihui-he/KL-Loss 摘要 大规模的目标检测数据集在 ...

  7. OpenCV-Python-图像梯度

    图像梯度 我们知道一阶导数可以用来求极值.把图片想象成连续函数,因为边缘部分的像素值与旁边的像素明显有区别,所以对图片局部求极值,就可以得到整幅图片的边缘信息.不过图片是二维的离散函数,导数就变成了差 ...

  8. 第三次java作业

    编写“学生”类及其测试类. 5.1 “学生”类: ² 类名:Student ² 属性:姓名.性别.年龄.学号.5门课程的成绩 ² 方法1:在控制台输出各个属性的值. ² 方法2:计算平均成绩 ² 方法 ...

  9. Springboot @Transactional Mysql事务 无效

    JPA默认创建的表是MyISAM引擎,MyISAM引擎不支持事务操作 所以需要将将数据库引擎改为InnoDB 配置修改 spring.jpa.database-platform=org.hiberna ...

  10. Flume-ng高可用集群负载安装与配置

    1. 写在前面 flume-ng高可用长在大数据处理环节第一个出现,对于处理日志文件有很好的作用,本篇博客将详细介绍flume-ng的高可用负载均衡搭建 2. flume-ng高可用负载均衡描述 在一 ...