【bzoj4337】【Bjoi2015】树的同构

  • 题解

    • 无标号树的HASH:
    • 找到树的重心,以重心为根求出括号序列;
    • 由于树的重心最多只有两个,取字典序的最小括号序列HASH即可
    • 树的括号序列$s_{u}="(s_{v_{1}},s_{v_{2}},s_{v_{3}},...,s_{v_{n}})"$,同时字典序$s_{v_{1}} <= s_{v_{2}} <= ,... $ 
    • 有标号树的HASH:
    • 个人认为可以直接$prufer$序列$HASH$
    • 或者直接将儿子排个序$hash$,(总之乱搞
    •  1 #include<bits/stdc++.h>
       2 #define ll long long
       3 #define mod 998244353
       4 using namespace std;
       5 const int N=51;
       6 int n,m,hd[N],o,sz[N],mx[N],Mx,tot;
       7 struct Edge{int v,nt;}E[N<<1];
       8 map<int,int>h;
       9 string now,s[N],tmp[N];
      10 void adde(int u,int v){
      11     E[o]=(Edge){v,hd[u]};hd[u]=o++;
      12     E[o]=(Edge){u,hd[v]};hd[v]=o++;
      13 }
      14 void get_rt(int u,int fa){
      15     sz[u]=1;mx[u]=0;
      16     for(int i=hd[u];~i;i=E[i].nt){
      17         int v=E[i].v;
      18         if(v==fa)continue;
      19         get_rt(v,u);
      20         sz[u]+=sz[v];
      21         mx[u]=max(mx[u],sz[v]);
      22     }
      23     mx[u]=max(m-sz[u],mx[u]);
      24     if(mx[u]<Mx)Mx=mx[u];
      25 }
      26 void dfs(int u,int fa){
      27     s[u]="(";
      28     for(int i=hd[u];~i;i=E[i].nt){
      29         int v=E[i].v;
      30         if(v==fa)continue;
      31         dfs(v,u);
      32     }
      33     tot=0;
      34     for(int i=hd[u];~i;i=E[i].nt){
      35         int v=E[i].v;
      36         if(v==fa)continue;
      37         tmp[++tot]=s[v];
      38     }
      39     sort(tmp+1,tmp+tot+1);
      40     for(int i=1;i<=tot;i++)s[u]=s[u]+tmp[i];
      41     s[u]+=")";
      42 }
      43 int main(){
      44     #ifndef ONLINE_JUDGE
      45     freopen("bzoj4337.in","r",stdin);
      46     freopen("bzoj4337.out","w",stdout);
      47     #endif
      48     scanf("%d",&n);
      49     for(int I=1;I<=n;I++){
      50         o=1;memset(hd,-1,sizeof(hd));
      51         scanf("%d",&m);
      52         for(int i=1,x;i<=m;i++){
      53             scanf("%d",&x);
      54             if(x)adde(x,i);
      55         }
      56         Mx=m;get_rt(1,0);
      57         now="";
      58         for(int i=1;i<=m;i++)if(Mx==mx[i]){
      59             dfs(i,0);
      60             if(now<s[i])now=s[i];
      61         }
      62         ll x=0;
      63         for(int i=0;i<(int)now.length();i++){
      64             x = ((x<<1) + now[i])%mod;
      65         }
      66         //printf("%s\n",now.c_str());
      67         if(!h[x])h[x]=I;
      68         printf("%d\n",h[x]);
      69     }
      70     return 0;
      71 }
      bzoj4337

       


posted @ 2019-01-08 21:52  大米饼  阅读(254)  评论(0编辑  收藏  举报