题意:
给两颗无根树,询问是否同构
解法:
网络上有各种简单的解法,不说,就说俺这个繁琐的T_T不过学了很多树的操作。
首先求两棵树的重心(iff 去掉了这个点之后最大子树最小)
然后把Tree 按照重心为根hash一下,如果有两个点的话求min即可。最后比较hash值是否相等。
。。。。。为了防止错误,把以上过程重复N 次(1次32MS , 100次500MS +)
char str[2][5000]; VI edge[5000]; int dp[5000] , subtree[5000] , ans; int tot , n; int pos; void build(int x , int r){ while(pos < n && str[x][pos] == '0'){ ++tot; edge[r].PB(tot); edge[tot].PB(r); ++pos; build(x , tot); } ++pos; return; } void dfs(int u , int v){ subtree[u] = 1; for (int i = 0 ; i < SZ(edge[u]) ; ++i){ int go = edge[u][i]; if (go == v) continue; dfs(go , u); checkMax(dp[u] , subtree[go]); subtree[u] += subtree[go]; } checkMax(dp[u] , tot - subtree[u]); checkMin(ans , dp[u]); // printf("%d %d\n" , u ,dp[u]); } ULL ret; ULL hash[5000]; ULL hashnumber , hashmodo; void hashtree(int u , int v){ hash[u] = 1; for (int i = 0 ; i < SZ(edge[u]) ; ++i){ int go = edge[u][i]; if (go == v) continue; hashtree(go , u); hash[u] *= (hash[go] + hashnumber) % hashmodo; hash[u] %= hashmodo; } // hash[u] %= (ULL)INF; } ULL Q(int x){ tot = 1; n = strlen(str[x]); for(int i = 0 ; i <= n ; ++i){ edge[i].clear(); } pos = 0; build(x , 1); RST(dp , subtree); ans = INF; dfs(1 , 0); ret = -1; for (int i = 1 ; i <= tot; ++i){ if(dp[i] == ans){ // cout << i << endl; hashtree(i , 0); checkMin(ret , hash[i]); } } // cout << ret << endl; return ret; } void solve(){ scanf("%s" , str[0]); scanf("%s" , str[1]); ULL t1 , t2; for (int i = 1 ; i <= 100 ; ++i){ hashnumber = rand32(); hashmodo = rand32(); t1 = Q(0); t2 = Q(1); // cout << "NOW:\n" << t1 << endl << t2 << endl; if (t1 != t2){ printf("different\n"); return; } } printf("same\n"); } int main(){ Rush solve(); }
注意:
1、建立树的时候pos 的使用方法
2、不能乘暴了ULL 之后一遍module,会错。
3、重复几遍是个好方法