• 仙人掌的同构(hash)


    关于仙人掌的同构,主要是我太蒟蒻了QAQ,问了好几位大佬才弄好。

    手撕仙人掌,你得先有手套 ,你得先了解以下基本知识

    a.点双连通分量,没什么好说得,仙人掌上有环,判环用点双

    b.树的hash点这里

    c.仙人掌点这里                              

    对于一棵仙人掌,我们通过一些方法来简化:                 

    我们最讨厌的是环,假如说没有环,那么树的hash还是蛮简单的。          

    OK那么就是圆方树了,如果你还不知道什么是圆方树,请自行百度或者点这里。

    当然对于判定仙人掌的同构,不需要一颗完整的圆方树,只需要在环中间建点

     单纯地表示一个环,使用最小表示法(这部分内容我稍后补充QAQ)

    单纯地表示一棵树,hash。

    嗯,如果你觉得我上面说得十分模糊,那么是正确的,因为还没有开始呢  ^_^

    (我其实是不会告诉你我没有用tarjan和完整的圆方树的)

    e.g.一个只有一个环的仙人掌

    假设我们是这样搜索的

    那么在dfs的过程中,要判定一个点在不在环上,记录它的父节点这样在回溯到4时,发现他有一个不是自己儿子的子节点(9)

    哈,那就是环的另一端了。

    这时抓出9,一直回溯父亲直到4被枚举到,整个环就被揪了出来。

    新建一个节点,(在圆方树里则称方点)依次连边。

    而对于非环上边直接连就好了

    像这样就建立了一个独立出原图的树(一位大佬是这样描述的)

    多么优雅的一棵树

    好了,现在它是无根的找一下树的重心

    新建一个根节点hash一下就好了^_^

    你真的觉得这就完了

    你太天真了


    环是不能这样子搞的

    正确打开方式:

    别忘了真正的环上点是有顺序的

    假如说这个环的方点(中间那个新建点)是根,跑最小表示法(然而我代码里没有这一项QAQ我改天加上)

    对于一个普通树节点比如说这样

    这样就可以了

     代码实现

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 typedef unsigned long long ult;
      6 const ult seed1=1324983271ull;
      7 const ult seed2=4327894239ull;
      8 const ult lth1=9301248721ull;
      9 const ult lth2=8317498371ull;
     10 int nt,mt;
     11 bool cmp(ult x,ult y)
     12 {
     13     return x<y;
     14 }
     15 struct pnt{
     16     int hd;
     17     int sh;
     18     int fa;
     19     int wgt;
     20     bool ong;
     21     bool vis;
     22     bool chkd;
     23     ult has;
     24 };
     25 struct ent{
     26     int twd;
     27     int lst;
     28 };
     29 struct Cactus{
     30     pnt p[300000];
     31     ent e[500000];
     32     ent r[500000];
     33     ult st[1000000];
     34     int rt[2];
     35     int n,m;
     36     int sqn;
     37     int cnt;
     38     int cmt;
     39     void e_ade(int f,int t)
     40     {
     41         cnt++;
     42         e[cnt].twd=t;
     43         e[cnt].lst=p[f].hd;
     44         p[f].hd=cnt;
     45     }
     46     void r_ade(int f,int t)
     47     {
     48         cmt++;
     49         r[cmt].twd=t;
     50         r[cmt].lst=p[f].sh;
     51         p[f].sh=cmt;
     52     }
     53     void tr_dfs(int x,int f)
     54     {
     55         p[x].vis=true;
     56         for(int i=p[x].hd;i;i=e[i].lst)
     57         {
     58             int to=e[i].twd;
     59             if((i^f)==1)continue;
     60             if(!p[to].vis)
     61             {
     62                 p[to].fa=x;
     63                 p[x].ong=false;
     64                 tr_dfs(to,i);
     65                 if(!p[x].ong)
     66                 {
     67                     r_ade(x,to);
     68                     r_ade(to,x);
     69                 }
     70             }else{
     71                 if(p[to].chkd)continue;
     72                 sqn++;
     73                 int u=x;
     74                 for(u=x;;u=p[u].fa)
     75                 {
     76                     r_ade(n+sqn,u);
     77                     r_ade(u,n+sqn);
     78                     p[u].ong=true;
     79                     if(u==to)break;
     80                 }
     81             }
     82         }
     83         p[x].chkd=true;
     84     }
     85     void gravity(int x,int f)
     86     {
     87         p[x].wgt=1;
     88         bool fl=true;
     89         for(int i=p[x].sh;i;i=r[i].lst)
     90         {
     91             int to=r[i].twd;
     92             if(to==f)continue;
     93             gravity(to,x);
     94             p[x].wgt+=p[to].wgt;
     95             if(p[to].wgt*2>sqn+n)
     96                 fl=false;
     97         }
     98         if((sqn+n-p[x].wgt)*2>sqn+n)
     99             fl=false;
    100         if(fl)
    101         {
    102             if(rt[0])
    103             {
    104                 rt[1]=x;
    105             }else{
    106                 rt[0]=x;
    107             }
    108         }
    109     }
    110     void Hash(int x,int f)
    111     {
    112         int top=0;
    113         for(int i=p[x].sh;i;i=r[i].lst)
    114         {
    115             int to=r[i].twd;
    116             if(to==f)continue;
    117             Hash(to,x);
    118         }
    119         if(x<=n)
    120         {
    121             for(int i=p[x].sh;i;i=r[i].lst)
    122             {
    123                 int to=r[i].twd;
    124                 if(to==f)continue;
    125                 st[++top]=p[to].has;
    126             }
    127             sort(st+1,st+top+1,cmp);
    128             p[x].has=seed1;
    129             for(int i=1;i<=top;i++)
    130             {
    131                 p[x].has=((p[x].has*lth1+st[i])^st[i])+st[i];
    132             }
    133         }else{
    134             int i;
    135             for(i=p[x].sh;i;i=r[i].lst)
    136             {
    137                 if(r[i].twd==f)
    138                     break;
    139             }
    140             for(i=r[i].lst;i;i=r[i].lst)
    141             {
    142                 int to=r[i].twd;
    143                 st[++top]=p[to].has;
    144             }
    145             for(i=p[x].sh;i;i=r[i].lst)
    146             {
    147                 int to=r[i].twd;
    148                 if(to==f)
    149                     break;
    150                 st[++top]=p[to].has;
    151             }
    152             ult tmp1=seed2,tmp2=seed2;
    153             for(i=1;i<=top;i++)
    154             {
    155                 tmp1=((tmp1*lth2+st[i])^st[i])+st[i];
    156             }
    157             for(i=top;i;i--)
    158             {
    159                 tmp2=((tmp2*lth2+st[i])^st[i])+st[i];
    160             }
    161             p[x].has=min(tmp1,tmp2);
    162             p[x].has*=lth2;
    163         }
    164     }
    165     ult solve(int nn,int mm)
    166     {
    167         n=nn;
    168         m=mm;
    169         cnt=1;
    170         for(int i=1;i<=m;i++)
    171         {
    172             int x;
    173             int y;
    174             scanf("%d%d",&x,&y);
    175             e_ade(x,y);
    176             e_ade(y,x);
    177         }
    178         tr_dfs(1,0);
    179         gravity(1,0);
    180         r_ade(0,rt[0]);
    181         if(rt[1])
    182         {
    183             r_ade(0,rt[1]);
    184             for(int i=p[rt[0]].sh;i;i=r[i].lst)
    185             {
    186                 if(r[i].twd==rt[1])
    187                     r[i].twd=0;
    188             }
    189             for(int i=p[rt[1]].sh;i;i=r[i].lst)
    190             {
    191                 if(r[i].twd==rt[0])
    192                     r[i].twd=0;
    193             }
    194         }
    195         Hash(0,0);
    196         return p[0].has;
    197     }
    198 }C[2];
    199 int main()
    200 {
    201     scanf("%d%d",&nt,&mt);
    202     if(C[0].solve(nt,mt)==C[1].solve(nt,mt))
    203     {
    204         printf("YES
    ");
    205     }else{
    206         printf("NO
    ");
    207     }
    208     return 0;
    209 }

    大概就是这样了^_^

  • 相关阅读:
    【Luogu】P3381最小费用最大流模板(SPFA找增广路)
    【Luogu】P1393动态逆序对(树套树)
    【Luogu】P2617Dynamic Ranking(树状数组套主席树)
    【Luogu】P2953牛的数字游戏(博弈论)
    【Luogu】P2530化工厂装箱员(DP)
    【Luogu】P3856公共子串(DP)
    【Luogu】P3847调整队形(DP)
    【Luogu】P3567Kur-Couriers(主席树)
    【Luogu】P3758可乐(矩阵优化DP)
    【Luogu】P1131时态同步(树形DP)
  • 原文地址:https://www.cnblogs.com/blog-Dr-J/p/9479054.html
Copyright © 2020-2023  润新知