Skip to content

树哈希 ​

题意:

判断树是否是对称的

做法一:随机种子+shift

cpp
mt19937_64 rng(time(0));
ULL shift(ULL x){
    x^=x<<13,x^=x>>7,x^=x<<17;
    return x;
}
void solve(){   
    int n;
    cin>>n;
    vector<int> adj[n+1];
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    ULL seed=rng();
    vector<int> sym(n+1);
    vector<ULL> h(n+1);
    function<void(int,int)> dfs=[&](int u,int fa){
        ULL sum=seed,xsum=0;
        for(auto v:adj[u]){
            if(v==fa)continue;
            dfs(v,u);
            sum+=shift(h[v]),xsum^=shift(h[v]);
        }
        h[u]=sum;
        if(!xsum){
            sym[u]=1;
            return;
        }
        for(auto v:adj[u]){
            if(v==fa)continue;
            if(xsum==shift(h[v])&&sym[v]){
                sym[u]=1;
                return;
            }
        }
    };
    dfs(1,0);
    cout<<(sym[1]?"YES\n":"NO\n");
}

做法二:AHU算法 $ O(nlogn) $

  • 严格正确
  • 使用map<vector<int>,int>
cpp
void solve(){   
    int n;
    cin>>n;
    vector<int> adj[n+1];
    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    map<vector<int>,int> mp;
    vector<int> h(n+1),sym(n+1);
    int idx=0;
    auto get=[&](vector<int> &v){
        if(!mp.count(v))mp[v]=++idx;
        return mp[v];
    };
    function<void(int,int)> dfs=[&](int u,int fa){
        vector<int> tmp;
        map<int,int> cnt;
        for(auto v:adj[u]){
            if(v==fa)continue;
            dfs(v,u);
            tmp.push_back(h[v]);
        }
        sort(tmp.begin(),tmp.end());
        h[u]=get(tmp);
        for(auto v:adj[u]){
            if(v==fa)continue;
            cnt[h[v]]++;
        }
        int cur=0,p;
        for(auto [x,y]:cnt){
            if(y&1)cur++,p=x;
        }
        if(!cur){
            sym[u]=1;
            return;
        }
        if(cur==1){
            for(auto v:adj[u]){
                if(v==fa)continue;
                if(h[v]==p&&sym[v]){
                    sym[u]=1;
                    return;
                }
            }
        }
    };
    dfs(1,0);
    cout<<(sym[1]?"YES\n":"NO\n");
}