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

来源:互联网 发布:手机特效软件 编辑:程序博客网 时间:2024/05/16 06:39

题意:

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

解法:

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