bzoj4474: [Jsoi2015]isomorphism

树hash啊

我的做法很垃圾,就是yy一种只有一个孩子时hash值和孩子一样的hash法

然后用重心去作为根遍历

这样有点问题,就是重心假如也是要删掉的那就gg了

那我们求tot的时候删掉的点就不管直接设为0,求重心的时候也不管这些删掉的点就可以了

 

其实

先把新的树建出来不好吗

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
const int _=1e2;
const int maxn=1e4+_;
const int maxt=20+3;

const LL hbase=233; LL mi[maxn];
void hyu(){mi[0]=1;for(int i=1;i<maxn;i++)mi[i]=mi[i-1]*hbase;}

struct TREE
{
    int id,ptt;
    TREE(){ptt=0;}
    struct node
    {
        int x,y,next;
    }a[2*maxn];int len,last[maxn],du[maxn];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
        
        du[x]++;
        if(du[x]==2)ptt++;
        else if(du[x]==3)ptt--;
    }
    
    //---------------------------------def--------------------------------------------
    
    int tot[maxn];
    void dfs(int x,int fr)
    {
        if(du[x]==2)tot[x]=0;
        else tot[x]=1;
        for(int k=last[x];k;k=a[k].next)
            if(a[k].y!=fr)dfs(a[k].y,x),tot[x]+=tot[a[k].y];
    }
    int G[maxn];
    void getrt(int x,int fr)
    {
        G[x]=0;
        for(int k=last[x];k;k=a[k].next)
        {
            int y=a[k].y;
            G[x]=max(G[x],tot[y]);
            if(y!=fr)
            {
                tot[x]-=tot[y];
                tot[y]+=tot[x];
                getrt(y,x);
                tot[y]-=tot[x];
                tot[x]+=tot[y];
            }
        }
    }
    
    //----------------------------------getrt--------------------------------------------
    
    int num;LL THash[2];
    LL h[maxn]; int tlen; LL tt[maxn];    
    void gethash(int x,int fr)
    {
        for(int k=last[x];k;k=a[k].next)
            if(a[k].y!=fr)gethash(a[k].y,x);
        tlen=0;
        for(int k=last[x];k;k=a[k].next)
            if(a[k].y!=fr)tt[++tlen]=h[a[k].y];
            
        if(tlen==0)h[x]=1;
        else 
        {
            sort(tt+1,tt+tlen+1);
            h[x]=(tlen-1)*31;
            for(int i=1;i<=tlen;i++)h[x]+=tt[i]*mi[i-1];
        }
    }
    
    //---------------------------------gethash-------------------------------------------
    
    void main()
    {
        int n,x,y;
        scanf("%d",&n);
        for(int i=1;i<n;i++)
        {
            scanf("%d%d",&x,&y);
            ins(x,y),ins(y,x);
        }
        ptt=n-ptt;
        
        dfs(1,0),getrt(1,0);
        num=0;
        int mn=(1<<30);
        for(int i=1;i<=n;i++)
            if(du[i]!=2)mn=min(mn,G[i]);
        for(int i=1;i<=n;i++)
            if(mn==G[i])
                gethash(i,0),THash[num++]=h[i];
    }
}tr[maxt];
bool check(int x,int y)
{
    for(int i=0;i<tr[x].num;i++)
        for(int j=0;j<tr[y].num;j++)
            if(tr[x].THash[i]==tr[y].THash[j])return true;
    return false;
}

int aslen,as[maxt];
bool cmp(int x,int y){return tr[x].ptt<tr[y].ptt;}
int main()
{
    freopen("a.in","r",stdin);
    freopen("a.out","w",stdout);
    int m;
    scanf("%d",&m);hyu();
    for(int i=1;i<=m;i++)
    tr[i].id=i,tr[i].main();
    for(int i=1;i<=m;i++)
    {
        bool bk=false;
        for(int j=1;j<=aslen;j++)
            if(check(i,as[j])){bk=true;break;}
        if(!bk)as[++aslen]=i;
    }
    sort(as+1,as+aslen+1,cmp);
    printf("%d\n",aslen);
    for(int i=1;i<aslen;i++)printf("%d ",tr[as[i]].ptt);
    printf("%d\n",tr[as[aslen]].ptt);
    
    return 0;
}

 

posted @ 2019-04-10 19:44  AKCqhzdy  阅读(175)  评论(0编辑  收藏  举报