• 洛谷 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;
    }
  • 相关阅读:
    Android ViewPager滑动导航菜单
    JQ操作select项
    radio控件name相同选出等于指定的value然后选中
    JQ随笔
    文本框宽度自动适应文本宽度<
    FindControl 找控件
    验证字母不符合替换成空
    JQ获取当前触发事件控件ID
    Repeater绑定对应行的dropdownlist
    有向图强连通分量的Tarjan算法
  • 原文地址:https://www.cnblogs.com/kamimxr/p/11314822.html
Copyright © 2020-2023  润新知