【BZOJ4337】树的同构(树同构,哈希)
题意:
树是一种很常见的数据结构。
我们把N个点,N-1条边的连通无向图称为树。
若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树。
对于两个树T1和T2,如果能够把树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 }
null