Description

给定一个N,N<=50 000个节点的仙人掌,其是指每条边最多在一个环中的无向图,求仙人掌有多少种自同构。自同构是指得是图的顶点集合V到V的变换M,

以P1^a1*P2^a2...Pk^ak的形式输出,其中Pk是素数。

建圆方树,找到重心,如果重心有两个就在它们之间的边上插一个点,同构变换后重心不变

以重心为根得到有根树,对于树点,统计交换子树造成的同构,将所有贡献累乘得到答案,对于环点,如果不是重心,就只有翻转这个环能产生新的同构,否则这个环除了翻转还可以旋转,用hash处理这些情况。注意处理环的时候需要把环点的相邻点排成原来在仙人掌上的顺序。

  1. #include<cstdio>
  2. #include<algorithm>
  3. typedef unsigned long long u64;
  4. const int N=;
  5. int n,m,fac[N];
  6. int es[N],enx[N],e0[N],e1[N],ep=;
  7. bool _c[N];
  8. void ae(int*e,int a,int b){
  9. es[ep]=b;enx[ep]=e[a];e[a]=ep++;
  10. es[ep]=a;enx[ep]=e[b];e[b]=ep++;
  11. }
  12. void de(int*e,int a,int b){
  13. for(int*i=e+a;*i;i=enx+*i){
  14. int u=es[*i];
  15. if(u==b){
  16. *i=enx[*i];
  17. return;
  18. }
  19. }
  20. }
  21. int dfn[N],low[N],tk=,ss[N],sp=,n1;
  22. void tj(int w,int pa){
  23. dfn[w]=low[w]=++tk;
  24. ss[++sp]=w;
  25. for(int i=e0[w];i;i=enx[i]){
  26. int u=es[i];
  27. if(!u)continue;
  28. if(!dfn[u]){
  29. es[i^]=;
  30. tj(u,w);
  31. es[i^]=w;
  32. if(ss[sp]==u)--sp,ae(e1,w,u);
  33. }else if(dfn[u]<dfn[w]){
  34. int rp=;
  35. ae(e1,u,++n1);
  36. _c[n1]=;
  37. while(sp&&dfn[ss[sp]]>dfn[u])ae(e1,ss[sp--],n1);
  38. }
  39. }
  40. }
  41. int sz[N],cg[],cgp=,rt;
  42. void f1(int w,int pa){
  43. bool is=;
  44. sz[w]=;
  45. for(int i=e1[w];i;i=enx[i]){
  46. int u=es[i];
  47. if(u==pa)continue;
  48. f1(u,w);
  49. sz[w]+=sz[u];
  50. if(sz[u]*>n1)is=;
  51. }
  52. if(sz[w]*<n1)is=;
  53. if(is)cg[cgp++]=w;
  54. }
  55. u64 h[N],h1[N],h2[N];
  56. int cs[N],cp;
  57. bool cmp_h(int a,int b){return h[a]<h[b];}
  58. int a1[N],a2[N],mx=;
  59. u64 a3[N];
  60. void mul(int x){
  61. ++a1[x];
  62. if(x>mx)mx=x;
  63. }
  64. void mulfac(int x){
  65. ++a2[x];
  66. if(x>mx)mx=x;
  67. }
  68. void f2(int w,int pa){
  69. for(int i=e1[w];i;i=enx[i]){
  70. int u=es[i];
  71. if(u!=pa)f2(u,w);
  72. }
  73. cp=;
  74. for(int i=e1[w],d=;i;i=enx[i]){
  75. int u=es[i];
  76. if(u==pa){
  77. d=;
  78. continue;
  79. }
  80. if(d)cs[cp++]=u;
  81. }
  82. for(int i=e1[w];i;i=enx[i]){
  83. int u=es[i];
  84. if(u==pa)break;
  85. cs[cp++]=u;
  86. }
  87. if(_c[w]){
  88. if(w==rt){
  89. u64 p0=,pp=;
  90. for(int i=;i<=cp;++i){
  91. h1[i]=h1[i+cp]=h2[i]=h2[i+cp]=h[cs[i-]];
  92. pp*=p0;
  93. }
  94. for(int i=;i<=cp*;++i)h1[i]+=h1[i-]*p0;
  95. for(int i=cp*;i;--i)h2[i]+=h2[i+]*p0;
  96. int c=;
  97. for(int i=cp;i<cp*;++i)c+=(h1[i]-h1[i-cp]*pp==h1[cp]);
  98. for(int i=cp;i;--i)c+=(h2[i]-h2[i+cp]*pp==h1[cp]);
  99. mul(c);
  100. }else{
  101. u64 h1=,h2=;
  102. for(int i=;i<cp;++i)h1=h1*+h[cs[i]];
  103. for(int i=cp-;i>=;--i)h2=h2*+h[cs[i]];
  104. if(h1==h2)mul();
  105. h[w]=std::min(h1,h2);
  106. h[w]^=h[w]>>^h[w]*<<^41546541735416351llu;
  107. }
  108. }else{
  109. std::sort(cs,cs+cp,cmp_h);
  110. h[w]=;
  111. for(int i=,j=;i<cp;i=j){
  112. for(;j<cp&&h[cs[i]]==h[cs[j]];++j);
  113. mulfac(j-i);
  114. }
  115. for(int i=;i<cp;++i)h[w]=h[w]*+h[cs[i]];
  116. h[w]^=h[w]>>^h[w]*<<^12218653252112541llu;
  117. }
  118. }
  119. int _(){
  120. int x=,c=getchar();
  121. while(c<)c=getchar();
  122. while(c>)x=x*+c-,c=getchar();
  123. return x;
  124. }
  125. int ps[N],pp,mp[N],ed[N];
  126. bool np[N];
  127. int main(){
  128. n=_();m=_();
  129. n1=n;
  130. for(int i=;i<m;++i){
  131. pp=_();
  132. for(int j=;j<pp;++j)ps[j]=_();
  133. for(int j=;j<pp-;++j)ae(e0,ps[j],ps[j+]);
  134. }
  135. for(int w=;w<=n;++w){
  136. for(int i=e0[w];i;i=enx[i]){
  137. int u=es[i];
  138. if(ed[u]!=w)ed[u]=w;
  139. else if(u>w)--a1[];
  140. }
  141. }
  142. tj(,);
  143. f1(,);
  144. if(cgp==){
  145. if(_c[cg[]])rt=cg[];
  146. else if(_c[cg[]])rt=cg[];
  147. else{
  148. rt=++n1;
  149. ae(e1,n1,cg[]);
  150. ae(e1,n1,cg[]);
  151. de(e1,cg[],cg[]);
  152. de(e1,cg[],cg[]);
  153. }
  154. }else rt=cg[];
  155. f1(rt,);
  156. f2(rt,);
  157. for(int i=mx;i;--i)a2[i]+=a2[i+];
  158. for(int i=mx;i;--i)a2[i]+=a1[i];
  159. pp=;
  160. for(int i=;i<=mx;++i){
  161. if(!np[i])ps[pp++]=mp[i]=i;
  162. for(int j=;j<pp&&i*ps[j]<=mx;++j){
  163. np[i*ps[j]]=;
  164. mp[i*ps[j]]=ps[j];
  165. if(i%ps[j]==)break;
  166. }
  167. }
  168. for(int i=;i<=mx;++i){
  169. for(int x=i;x>;x/=mp[x])a3[mp[x]]+=a2[i];
  170. }
  171. pp=;
  172. for(int i=;i<=mx;++i)if(a3[i])ps[pp++]=i;
  173. printf("%d\n",pp);
  174. for(int j=;j<pp;++j)printf("%d %lld\n",ps[j],a3[ps[j]]);
  175. return ;
  176. }

bzoj3871: [Neerc2013 C]Cactus Automorphisms || 3899: 仙人掌树的同构的更多相关文章

  1. BZOJ3899 仙人掌树的同构(圆方树+哈希)

    考虑建出圆方树.显然只有同一个点相连的某些子树同构会产生贡献.以重心为根后(若有两个任取一个即可),就只需要处理子树内部了. 如果子树的根是圆点,其相连的同构子树可以任意交换,方案数乘上同构子树数量的 ...

  2. 03-树1 树的同构 (C语言链表实现)

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h& ...

  3. PAT 03-树1 树的同构 (25分)

    给定两棵树T1和T2.如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是"同构"的.例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A.B.G的左右孩子互换后 ...

  4. BZOJ 4337: BJOI2015 树的同构 树hash

    4337: BJOI2015 树的同构 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=4337 Description 树是一种很常见的数 ...

  5. SDUT 3340 数据结构实验之二叉树一:树的同构

    数据结构实验之二叉树一:树的同构 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 给定两棵树 ...

  6. PTA 深入虎穴 (正解)和树的同构

    在上一篇博客中分享了尝试用单链表修改程序,虽然在Dev上运行没有错误,但是PTA设置的测试点有几个没有通过,具体不清楚问题出现在哪里,所以现在把之前正确的程序放在这里. 7-2 深入虎穴 (30 分) ...

  7. 4337: BJOI2015 树的同构

    题解: 树的同构的判定 有根树从根开始进行树hash 先把儿子的f进行排序 $f[i]=\sum_{j=1}^{k} { f[j]*prime[j]} +num[i]$(我没有仔细想这样是不是树是唯一 ...

  8. [BJOI2015]树的同构

    嘟嘟嘟 判断树的同构的方法就是树上哈希. 如果树是一棵有根树,那么只要从根节点出发dfs,每一个节点的哈希值等于按传统方式算出来的子树的哈希值的结果.需要注意的是,算完子树的哈希值后要先排序再加起来, ...

  9. bzoj4337树的同构

    树是一种很常见的数据结构. 我们把N个点,N-1条边的连通无向图称为树. 若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树. 对于两个树T1和T2,如果能够把树T1的所有点重 ...

随机推荐

  1. 【转载】Android Bug分析系列:第三方平台安装app启动后,home键回到桌面后点击app启动时会再次启动入口类bug的原因剖析

    前言 前些天,测试MM发现了一个比较奇怪的bug. 具体表现是: 1.将app包通过电脑QQ传送到手机QQ上面,点击安装,安装后选择打开app (此间的应用逻辑应该是要触发 [闪屏页Activity] ...

  2. 递归算法,如何把list中父子类对象递归成树

    以前写代码for循环写的多,递归除了在大学学习以外,真没怎么用过! 最近项目中使用到了关于族谱排列的问题,就是怎么把数据库里的多个子父类people对象,在界面中用树的结构展示出来 假设数据库中peo ...

  3. L224

    Astronomers have revealed details of mysterious signals emanating from a distant galaxy, picked up b ...

  4. avalon源码阅读(1)

    来源 写angularJS源码阅读系列的时候,写的太垃圾了. 一个月后看,真心不忍直视,以后有机会的话得重写. 这次写avalonJS,希望能在代码架构层面多些一点,少上源码.多写思路. avalon ...

  5. mysql 聚合函数

    1.sum 用法 有这种类型的数据: id date user_id result 1 2015-05-04 1 win 2 2015-05-06 1 loss 3 2015-05-09 2 loss ...

  6. rem & em初探

    Rem为单位 CSS3的出现,他同时引进了一些新的单位,包括我们今天所说的rem.在W3C官网上是这样描述rem的——“font size of the root element” .下面我们就一起来 ...

  7. STM32中断定时,控制LED灯

    #include "led.h" void TIM3_Int_Init(u16 arr,u16 psc) { TIM_TimeBaseInitTypeDef TIM_TimeBas ...

  8. BZOJ3925: [Zjoi2015]地震后的幻想乡【概率期望+状压DP】

    Description 傲娇少女幽香是一个很萌很萌的妹子,而且她非常非常地有爱心,很喜欢为幻想乡的人们做一些自己力所能及的事情来帮助他们. 这不,幻想乡突然发生了地震,所有的道路都崩塌了.现在的首要任 ...

  9. jQuery插件制作方法详解

        jQuery插件制作方法详解   jquery插件给我的感觉清一色的清洁,简单.如Jtip,要使用它的功能,只需要在你的元素的class上加 上Jtip,并引入jtip.js及其样式即可以了. ...

  10. LG4454 【[CQOI2018]破解D-H协议】

    先谈一下BSGS算法(传送门) 但是上面这位的程序实现比较繁琐,看下面这位的. clover_hxy这样说 bsgs算法,又称大小步算法(某大神称拔山盖世算法). 主要用来解决 A^x=B(mod C ...