题意:
给两颗无根树,询问是否同构
解法:
网络上有各种简单的解法,不说,就说俺这个繁琐的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、重复几遍是个好方法