只有一个点入度为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;
}
ustc 1117
#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;
}