zoukankan      html  css  js  c++  java
  • BZOJ4754 JSOI2016独特的树叶(哈希)

      判断两棵无根树是否同构只需要把重心提作根哈希即可。由于只添加了一个叶子,重心的位置几乎不发生偏移,所以直接把两棵树的重心提起来,逐层找哈希值不同且对应的两子树即可。被一个普及组子问题卡一年。

    #include<iostream> 
    #include<cstdio>
    #include<cmath>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define ll long long
    #define ul unsigned long long
    #define N 100010
    char getc(){char c=getchar();while ((c<'A'||c>'Z')&&(c<'a'||c>'z')&&(c<'0'||c>'9')) c=getchar();return c;}
    int gcd(int n,int m){return m==0?n:gcd(m,n%m);}
    int read()
    {
        int x=0,f=1;char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
        while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
        return x*f;
    }
    int n,ans,f[N],g[N];
    struct tree
    {
        int p[N],t,size[N],root;
        ul hax[N],f[N];
        struct data{int to,nxt;}edge[N<<1];
        void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
        void dfs(int k,int from)
        {
            size[k]=1;
            for (int i=p[k];i;i=edge[i].nxt)
            if (edge[i].to!=from)
            dfs(edge[i].to,k),size[k]+=size[edge[i].to];
        }
        int findroot(int k,int s)
        {
            int mx=0;
            for (int i=p[k];i;i=edge[i].nxt)
            if (size[edge[i].to]<size[k]&&size[edge[i].to]>size[mx]) mx=edge[i].to;
            if (size[mx]*2>s) return findroot(mx,s);
            else return k;
        }
        void refind()
        {
            for (int i=p[root];i;i=edge[i].nxt)
            if (size[edge[i].to]*2>=size[root]) {root=edge[i].to;break;}
        }
        void gethash(int k,int from)
        {
            for (int i=p[k];i;i=edge[i].nxt)
            if (edge[i].to!=from) gethash(edge[i].to,k);
            int cnt=0;
            for (int i=p[k];i;i=edge[i].nxt)
            if (edge[i].to!=from) f[++cnt]=hax[edge[i].to];
            sort(f+1,f+cnt+1);
            hax[k]=0;
            for (int i=1;i<=cnt;i++) hax[k]=hax[k]*107+f[i];
            hax[k]+=size[k]*509;
        }
    }a,b;
    bool cmp(const int&x,const int&y)
    {
        return a.hax[x]<a.hax[y];
    }
    bool cmp2(const int&x,const int&y)
    {
        return b.hax[x]<b.hax[y]||b.hax[x]==b.hax[y]&&x>y;
    }
    void work(int x,int y)
    {
        int cnt=0,cnt2=0;
        for (int i=a.p[x];i;i=a.edge[i].nxt)
        if (a.size[a.edge[i].to]<a.size[x]) f[++cnt]=a.edge[i].to; 
        for (int i=b.p[y];i;i=b.edge[i].nxt)
        if (b.size[b.edge[i].to]<b.size[y]) g[++cnt2]=b.edge[i].to; 
        sort(f+1,f+cnt+1,cmp);
        sort(g+1,g+cnt2+1,cmp2);
        if (cnt>cnt2||cnt2>cnt+1) return;
        if (cnt2==cnt+1)
        {
            int t=0;
            for (int i=1,j=1;i<=cnt2;i++,j++)
            if (a.hax[f[j]]!=b.hax[g[i]]||j>cnt) if (!t) t=g[i++];else return;
            if (t) ans=min(ans,t);
            return;
        }
        if (cnt2==cnt)
        {
            int u,v;
            for (u=1;u<=cnt;u++) if (a.hax[f[u]]!=b.hax[g[u]]) break;
            if (!u) return;
            if (a.hax[f[u]]<b.hax[g[u]]) for (v=u;v<cnt;v++) if (a.hax[f[v+1]]!=b.hax[g[v]]) break;
            if (!v) return;
            for (int i=v+1;i<=cnt;i++) if (a.hax[f[i]]!=b.hax[g[i]]) return;
            for (int i=1;i<=cnt;i++) if (b.hax[g[v]]==b.hax[g[i]]) work(f[u],g[i]);
        }
    }
    int main()
    {
    #ifndef ONLINE_JUDGE
        freopen("bzoj4754.in","r",stdin);
        freopen("bzoj4754.out","w",stdout);
        const char LL[]="%I64d
    ";
    #else
        const char LL[]="%lld
    ";
    #endif
        n=read();ans=n+1;
        for (int i=1;i<n;i++)
        {
            int x=read(),y=read();
            a.addedge(x,y),a.addedge(y,x);
        }
        for (int i=1;i<=n;i++)
        {
            int x=read(),y=read();
            b.addedge(x,y),b.addedge(y,x);
        }
        a.dfs(1,1),b.dfs(1,1);
        a.root=a.findroot(1,n),b.root=b.findroot(1,n+1);
        a.dfs(a.root,a.root),b.dfs(b.root,b.root);
        a.gethash(a.root,a.root),b.gethash(b.root,b.root);
        work(a.root,b.root);
        if (n&1) a.refind();
        else b.refind();
        a.dfs(a.root,a.root),b.dfs(b.root,b.root);
        a.gethash(a.root,a.root),b.gethash(b.root,b.root);
        work(a.root,b.root);
        cout<<ans;
        return 0;
    }
  • 相关阅读:
    032 Gradle 下载的依赖jar包在哪?
    031 can't rename root module,Android Studio修改项目名称
    030 Cannot resolve symbol'R' 问题解决汇总大全
    029 Android Studio层级显示目录文件
    028 You are about to commit CRLF line separators to the Git repository.It is recommended to set the core. autocrlf Git attribute to true to avoid line separator issues If you choose Fix and Comit ,
    027 【Android基础知识】Android Studio 编译慢及 Adb connection Error:远程主机强迫关闭了一个现有的连接
    026 Android Studio 和Gradle版版本对应关系
    025 Cause: org.jetbrains.plugins.gradle.tooling.util.ModuleComponentIdentifierIm
    024 Android Studio上传项目到Github 最全记录
    023 解决AndroidStudio下载gradle慢的问题
  • 原文地址:https://www.cnblogs.com/Gloid/p/9961329.html
Copyright © 2011-2022 走看看