• 【BZOJ4337】树的同构(树同构,哈希)


    题意:

    树是一种很常见的数据结构。

    我们把N个点,N-1条边的连通无向图称为树。

    若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树。

    对于两个树T1T2,如果能够把树T1T1的所有点重新标号,使得树T1和树T2完全相同,那么这两个树是同构的。也就是说,它们具有相同的形态。

    现在,给你M个有根树,请你把它们按同构关系分成若干个等价类。

    n,m<=50

    思路:无根树同构,直接上哈希板子

    BZOJ上没有C++11被搞了

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 typedef unsigned int uint;
      5 typedef unsigned long long ull;
      6 typedef long double ld;
      7 typedef pair<int,int> PII;
      8 typedef pair<ll,ll> Pll;
      9 typedef vector<int> VI;
     10 typedef vector<PII> VII;
     11 typedef pair<ll,ll>P;
     12 #define N  500010
     13 #define M  1000000
     14 #define INF 1e9
     15 #define fi first
     16 #define se second
     17 #define MP make_pair
     18 #define pb push_back
     19 #define pi acos(-1)
     20 #define mem(a,b) memset(a,b,sizeof(a))
     21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
     22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
     23 #define lowbit(x) x&(-x)
     24 #define Rand (rand()*(1<<16)+rand())
     25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
     26 #define ls p<<1
     27 #define rs p<<1|1
     28 #define fors(i) for(auto i:e[x]) if(i!=p)
     29 
     30 const int MOD=1e9+7,inv2=(MOD+1)/2;
     31       double eps=1e-6;
     32       int dx[4]={-1,1,0,0};
     33       int dy[4]={0,0,-1,1};
     34 
     35 int ra[N];
     36 
     37 int read()
     38 {
     39    int v=0,f=1;
     40    char c=getchar();
     41    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
     42    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
     43    return v*f;
     44 }
     45 
     46 int pw(int x,int y)
     47 {
     48     int res=1;
     49     while(y)
     50     {
     51         if(y&1) res=1ll*res*x%MOD;
     52         x=1ll*x*x%MOD;
     53         y>>=1;
     54     }
     55     return res;
     56 }
     57 
     58 int inv(int x)
     59 {
     60     return pw(x,MOD-2);
     61 }
     62 
     63 struct Sub
     64 {
     65     VI S;
     66     int d1,d2,H1,H2;
     67     Sub(){d1=d2=0; S.clear();}
     68 
     69     void add(int d,int v)
     70     {
     71         S.pb(v);
     72         if(d>d1) d2=d1,d1=d;
     73          else if(d>d2) d2=d;
     74     }
     75 
     76     int Hash()
     77     {
     78         H1=H2=1;
     79         for(int i:S)
     80         {
     81             H1=1ll*H1*(ra[d1]+i)%MOD;
     82             H2=1ll*H2*(ra[d2]+i)%MOD;
     83         }
     84         return H1;
     85     }
     86 
     87     PII del(int d,int v)
     88     {
     89         if(d==d1) return {d2+1,1ll*H2*inv(ra[d2]+v)%MOD};
     90         return {d1+1,1ll*H1*inv(ra[d1]+v)%MOD};
     91     }
     92 };
     93 
     94 PII U[N];
     95 int n,i,x,y,A[N],b[100][100];
     96 Sub T[N];
     97 VI e[N];
     98 
     99 void prepare(int n)
    100 {
    101     rep(i,0,n) ra[i]=rand()%MOD;
    102 }
    103 
    104 void add(int x,int y)
    105 {
    106     e[x].pb(y);
    107 }
    108 
    109 void dfsD(int x,int p)
    110 {
    111     T[x]=Sub();
    112     fors(i) dfsD(i,x),T[x].add(T[i].d1+1,T[i].H1);
    113     T[x].Hash();
    114 }
    115 
    116 void dfsU(int x,int p)
    117 {
    118     if(p) T[x].add(U[x].fi,U[x].se);
    119     A[x]=T[x].Hash();
    120     fors(i) U[i]=T[x].del(T[i].d1+1,T[i].H1),dfsU(i,x);
    121 }
    122 
    123 int main()
    124 {
    125     //freopen("1.in","r",stdin);
    126     srand(23333);
    127     prepare(1e5);
    128     int m=read();
    129     rep(v,1,m)
    130     {
    131         n=read();
    132         int root=0;
    133         rep(i,1,n) e[i].clear();
    134         rep(i,1,n) A[i]=0;
    135         rep(i,1,n)
    136         {
    137             int x=read();
    138             if(x==0){root=i; continue;}
    139             add(x,i);
    140             add(i,x);
    141         }
    142         dfsD(1,0);
    143         dfsU(1,0);
    144         sort(A+1,A+n+1);
    145         //rep(i,1,n) printf("%d ",A[i]);
    146         //printf("
    ");
    147         int flag=0;
    148         rep(i,1,v-1)
    149         {
    150             flag=1;
    151             rep(j,1,n)
    152              if(A[j]!=b[i][j]){flag=0; break;}
    153             if(flag){printf("%d
    ",i); break;}
    154         }
    155         if(!flag) printf("%d
    ",v);
    156         rep(i,1,n) b[v][i]=A[i];
    157     }
    158 
    159     return 0;
    160 }
  • 相关阅读:
    TCP 的 Keepalive 和 HTTP 的 Keep-Alive 是一个东西吗?
    图解 Redis | 差点崩溃了,还好有主从复制
    图解 Redis | 不多说了,这就是 RDB 快照
    图解 Redis | 不就是 AOF 持久化嘛
    看书的一点小建议!
    图解高性能网络架构:Reactor 和 Proactor
    面试官:什么是死锁?怎么排查死锁?怎么避免死锁?
    HTTP/1.1 有点慢,我想优化下!
    Linux 内核和 Windows 内核有什么区别?
    提高代码颜值的几个小技巧
  • 原文地址:https://www.cnblogs.com/myx12345/p/11778453.html
Copyright © 2020-2023  润新知