只有一个点入度为0的树是外向树,只有一个点出度为0的树是内向树,这两种是典型的有根树
平时见到的无向图中的树是无根树
1.判断树同构本质是哈希,每个点的权值是这个点的子树的权值和,这里所谓的权值是随机数产生的
由于随机性,树上某一组合不同都会导致最终的结果不一样,所以只要判断根的权值是否相等就可以确定同构
2.随机性决定了不确定性,但正确率还是很高
3.可以不用哈希,用“最小表示”表示出一个点的子节点,再比较最小表示产生的序列是否相同,代码烦,比较复杂,不见得快
poj 1635
#include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <cmath> using namespace std; #define mod 9997 char str1[10000]; char str2[10000]; int h[10000],len,cur; char *p; int hashing(int j) { int sum=h[j]; while(*p!='\0'&&*p++=='0') //每次检查是否1时还加1,使回溯时跳出循环 { sum=(sum+hashing(j+1)*h[j])%mod; } return (sum*sum)%mod; } int main () { for(int i=0;i<10000;++i) h[i]=rand()%mod; int test;scanf("%d",&test); while(test--) { scanf("%s%s",str1,str2); if(strlen(str1)!=strlen(str2)) { printf("different\n"); continue; } len=strlen(str1); p=str1; int a=hashing(1); p=str2; int b=hashing(1);// 多次hash 可以避免冲突,提高正确率 if(a==b) printf("same\n"); else printf("different\n"); } system("pause"); return 0; }
#include <iostream> #include <cstring> #include <cstdio> #include <cstdlib> #include <cmath> #include <vector> using namespace std; #define mod 9973 int h[1050]; vector<int>s[1050]; vector<int>p[1050]; int vis[1050]; int n; int Hash(int cur,int depth) { int sum=h[depth];vis[cur]=1; for(int i=0;i<s[cur].size();++i) if(!vis[s[cur][i]]) sum=(sum+Hash(s[cur][i],depth+1)*h[depth])%mod; return (sum*sum)%mod; } int Hash2(int cur,int depth) { int sum=h[depth];vis[cur]=1; for(int i=0;i<p[cur].size();++i) if(!vis[p[cur][i]]) sum=(sum+Hash2(p[cur][i],depth+1)*h[depth])%mod; return (sum*sum)%mod; } int main () { for(int i=0;i<1040;++i) h[i]=rand()%mod; int test;scanf("%d",&test); while(test--) { scanf("%d",&n); for(int i=1;i<=n;++i) s[i].clear(),p[i].clear(); int u,v; for(int i=1;i<n;++i) { scanf("%d%d",&u,&v); s[u].push_back(v); s[v].push_back(u); } for(int i=1;i<n;++i) { scanf("%d%d",&u,&v); p[u].push_back(v); p[v].push_back(u); } memset(vis,0,sizeof(vis)); int a=Hash(1,1); bool flag=false; for(int i=1;i<=n;++i) { memset(vis,0,sizeof(vis)); int b=Hash2(i,1); if(a==b) flag=true; if(flag) break; } if(flag) printf("same\n"); else printf("different\n"); } system("pause"); return 0; }