【POJ 1635】树基本操作(Tree 重心 + Tree hash + ULL 的用法)

题意:

给两颗无根树,询问是否同构

解法:

网络上有各种简单的解法,不说,就说俺这个繁琐的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、重复几遍是个好方法

你可能感兴趣的:(【POJ 1635】树基本操作(Tree 重心 + Tree hash + ULL 的用法))