洛谷 P5043 树的同构 题解

题面

 

本题的难度其实不及紫题的难度。主要是在hash时的处理细节比较繁琐;

首先是树hash的模板:

long long treehash(int u,int fa)
{
    long long q[1001];
    long long num=0;
    long long ans=1;
    for(int i=head[u];i;i=star[i].nxt){
        int v=star[i].to;
        if(v==fa) continue;
        q[++num]=treehash(v,u);
    }
    sort(q+1,q+num+1);
    for(int i=1;i<=num;i++){
        ans=ans*2333+q[i];
    }
    return ans*2333+1;
}

对于无根树在数据不多的时候可以依次枚举每个点当根时的根节点的hash值,然后将这些树上hash值变为一组数的hash值;

然后n^2比较每棵树的线性hash值就可以了;

 

#include <bits/stdc++.h>
using namespace std;
struct littlestar{
    int to;
    int nxt;
}star[20010];
long long head[20010],cnt;
void add(int u,int v)
{
    star[++cnt].to=v;
    star[cnt].nxt=head[u];
    head[u]=cnt;
}
long long myhash[20010];
long long treehash(int u,int fa)
{
    long long q[1001];
    long long num=0;
    long long ans=1;
    for(int i=head[u];i;i=star[i].nxt){
        int v=star[i].to;
        if(v==fa) continue;
        q[++num]=treehash(v,u);
    }
    sort(q+1,q+num+1);
    for(int i=1;i<=num;i++){
        ans=ans*2333+q[i];
    }
    return ans*2333+1;
}
long long lala[20010];
long long ans[20010];
int main ()
{
    int t;
    cin>>t;
    for(int i=1;i<=t;i++){
        memset(head,0,sizeof(head));
        memset(lala,0,sizeof(lala));
        cnt=0;
        int n;
        cin>>n;
        int root=1;
        for(int j=1;j<=n;j++){
            int x;
            scanf("%d",&x);
            if(x==0){
                root=j;
                continue;
            } 
            add(x,j);
            add(j,x);        
        }
        for(int j=1;j<=n;j++) myhash[j]=treehash(j,0);
        sort(myhash+1,myhash+1+n);
        for(int j=1;j<=n;j++) lala[j]=lala[j-1]*myhash[j]+233;
        ans[i]=lala[n];
        for(int j=1;j<=i;j++){
            if(ans[i]==ans[j]){
                cout<<j<<endl;
                break;
            }
        }
    }
    return 0;
}

 

posted @ 2019-08-07 13:48  神之右大臣  阅读(271)  评论(0编辑  收藏  举报