1. 程式人生 > >樹的同構--poj 1635(有根樹)ustc 1117 (無根樹)

樹的同構--poj 1635(有根樹)ustc 1117 (無根樹)

只有一個點入度為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;
}