zoukankan      html  css  js  c++  java
  • 【BZOJ4337】[BJOI2015] 树的同构(哈希水题)

    点此看题面

    大致题意: 给你若干棵树,询问和每棵树同一形态的树编号的最小值。

    哈希

    这种东西显然哈希哈希就好了吧。。。

    反正我就对于树上每个点把它的每个子树大小(包括子树外点的个数)排序一边然后哈希起来,然后对于整棵树把所有节点哈希值排序一遍哈希起来,然后开个(map)判断有没有出现过就可以了。

    本来还以为要调下参的,结果还没反应过来就秒过了。。。(看来我选用的参数果然是幸运数字)

    代码

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 50
    #define add(x,y) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y)
    using namespace std;
    int Tt,n,rt,ee,lnk[N+5];struct edge {int to,nxt;}e[N];
    class TreeHasher
    {
    	private:
    		int s[N+5],Sz[N+5];
    		struct Hash//哈希
    		{
    			#define ull unsigned long long
    			#define RU Reg ull
    			#define CU Con ull&
    			ull x,y;I Hash() {x=y=0;}I Hash(CU a):x(a),y(a){}I Hash(CU a,CU b):x(a),y(b){}
    			I bool operator < (Con Hash& o) Con {return x^o.x?x<o.x:y<o.y;}
    			I Hash operator + (Con Hash& o) Con {return Hash(x+o.x,y+o.y);}
    			I Hash operator - (Con Hash& o) Con {return Hash(x-o.x,y-o.y);}
    			I Hash operator * (Con Hash& o) Con {return Hash(x*o.x,y*o.y);}
    		}seed,h[N+5];map<pair<Hash,Hash>,int> p;
    		I void dfs(CI x)//遍历子树
    		{
    			RI i;for(Sz[x]=1,i=lnk[x];i;i=e[i].nxt) dfs(e[i].to),Sz[x]+=Sz[e[i].to];//计算Size
    			RI t=0;for(i=lnk[x];i;i=e[i].nxt) s[++t]=Sz[e[i].to];x^rt&&(s[++t]=n-Sz[x]);//统计每个子树大小
    			for(sort(s+1,s+t+1),h[x]=0,i=1;i<=t;++i) h[x]=h[x]*seed+s[i];//排序后哈希
    		}
    	public:
    		I TreeHasher() {seed=Hash(20050521,302627441);}//初始化
    		I void Solve(CI id)
    		{
    			RI i;Hash Add(0,0),Mul(1,1);
    			for(dfs(rt),sort(h+1,h+n+1),i=1;i<=n;++i) Add=Add*seed+h[i],Mul=Mul*h[i];//把整棵树哈希值排序后再哈希
    			pair<Hash,Hash> now=make_pair(Add,Mul);printf("%d
    ",p[now]?p[now]:p[now]=id);//用map判断有没有出现过
    		}
    }H;
    int main()
    {
    	RI i,j,x;for(scanf("%d",&Tt),i=1;i<=Tt;++i)
    	{
    		for(scanf("%d",&n),ee=0,j=1;j<=n;++j) lnk[j]=0;
    		for(j=1;j<=n;++j) scanf("%d",&x),x?add(x,j):(rt=j);H.Solve(i);
    	}return 0;
    }
    
  • 相关阅读:
    extern C的作用详解
    UIWindow in iOS
    iOS会议和组织
    Fantageek翻译系列之《使用Autolayout显示变化高度的UITableViewCell》
    KVO的概述的使用
    Struts2 基于XML校验(易百教程)
    Maven项目中添加JDBC驱动
    org.dom4j.DocumentException: null Nested exception: null解决方法
    struts2中的数据类型自动转换
    struts2的拦截器
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/BZOJ4337.html
Copyright © 2011-2022 走看看