zoukankan      html  css  js  c++  java
  • 4337: BJOI2015 树的同构

    题解:

    树的同构的判定

    有根树从根开始进行树hash

    先把儿子的f进行排序

    $f[i]=sum_{j=1}^{k} { f[j]*prime[j]} +num[i]$(我没有仔细想这样是不是树是唯一的。。。反正过了)

    无根树先找到重心再作为根

    因为重心最多只有两个,复杂度仍旧O(n)

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    #define rint register int
    #define IL inline
    #define rep(i,h,t) for (int i=h;i<=t;i++)
    #define dep(i,t,h) for (int i=t;i>=h;i--)
    #define me(x) memset(x,0,sizeof(x))
    #define ll long long
    #define mep(x,y) memcpy(x,y,sizeof(y))
    #define mid ((h+t)>>1)
    #define ull unsigned ll
    namespace IO{
        char ss[1<<24],*A=ss,*B=ss;
        IL char gc()
        {
            return A==B&&(B=(A=ss)+fread(ss,1,1<<24,stdin),A==B)?EOF:*A++;
        }
        template<class T>void read(T &x)
        {
            rint f=1,c; while (c=gc(),c<48||c>57) if (c=='-') f=-1; x=(c^48);
            while (c=gc(),c>47&&c<58) x=(x<<3)+(x<<1)+(c^48); x*=f;
        }
        char sr[1<<24],z[20]; int Z,C=-1;
        template<class T>void wer(T x)
        {
            if (x<0) sr[++C]='-',x=-x;
            while (z[++Z]=x%10+48,x/=10);
            while (sr[++C]=z[Z],--Z);
        }
        IL void wer1() { sr[++C]=' ';}
        IL void wer2() { sr[++C]='
    ';}
        template<class T>IL void maxa(T &x,T y) { if (x<y) x=y;} 
        template<class T>IL void mina(T &x,T y) { if (x>y) x=y;}
        template<class T>IL T MAX(T x,T y) {return x>y?x:y;}
        template<class T>IL T MIN(T x,T y) {return x<y?x:y;}
    };
    using namespace IO;
    const int N=100;
    int head[N],n,m,l,num[N],f[N];
    struct re{
        int a,b;
    }e[N*2];
    bool q[1100];
    int zs[N];
    ull son[N][N],ans[N],g[N];
    IL void arr(int x,int y)
    {
        e[++l].a=head[x];
        e[l].b=y;
        head[x]=l;
    }
    void fdrt(int x,int y)
    {
        num[x]=1;
        for (rint u=head[x];u;u=e[u].a)
        {
            int v=e[u].b;
            if (v!=y)
            {
                fdrt(v,x);
                num[x]+=num[v];
                if (num[v]>f[x]) f[x]=num[v];
            }
        }
        if (n-num[x]>f[x]) f[x]=n-num[x];
    }
    void dfs(int x,int y)
    {
        num[x]=1;
        int cnt=0;
        for (rint u=head[x];u;u=e[u].a)
        {
            int v=e[u].b;
            if (v!=y)
            {
                dfs(v,x);
                son[x][++cnt]=g[v];
                num[x]+=num[v];
            }
        }
        sort(son[x]+1,son[x]+cnt+1);
        ull now=0;
        rep(i,1,cnt) now=now+son[x][i]*zs[i];
        now+=num[x];
        g[x]=now;
    }
    int main()
    {
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
        read(m);
        rep(i,2,1000)
          for (int j=2;j*i<=1000;j++)
            q[i*j]=1;
        int cnt=0;
        rep(i,501,1000)
          if (!q[i])
          {
              zs[++cnt]=i;
              if (cnt>=60) break;
          }
        rep(j,1,m)
        {
            me(head); read(n); me(f); l=0;
            rep(i,1,n)
            {
                int x,y; read(x);
                if (x) arr(x,i),arr(i,x);
            }
            fdrt(1,0);
            int ma=1e9;
            rep(i,1,n) ma=min(ma,f[i]);
            rep(i,1,n)
              if (f[i]==ma)
              {
                   dfs(i,0); maxa(ans[j],g[i]);
              }
        }
        rep(i,1,m)
          rep(j,1,m)
            if(ans[j]==ans[i])
            {
                cout<<j<<endl; break;
            }
        return 0; 
    }
  • 相关阅读:
    JZOJ 3845. 简单题(simple)
    JZOJ 3844. 统计损失(count)
    JZOJ 3843. 寻找羔羊(agnus)
    JZOJ 3833. 平坦的折线
    JZOJ 1956. 矩形
    JZOJ 3832. 在哪里建酿酒厂
    mysql 语法一 :case when详解
    阿里云推荐码
    redis配置文件详解(转)
    压力测试工具 webbench总结
  • 原文地址:https://www.cnblogs.com/yinwuxiao/p/10095490.html
Copyright © 2011-2022 走看看