【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("\n");
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\n",i); break;}
154         }
155         if(!flag) printf("%d\n",v);
156         rep(i,1,n) b[v][i]=A[i];
157     }
158 
159     return 0;
160 }

 

posted on 2019-11-01 17:49  myx12345  阅读(344)  评论(0编辑  收藏  举报

导航