樹的同構--poj 1635(有根樹)ustc 1117 (無根樹)
阿新 • • 發佈:2019-02-16
只有一個點入度為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; }