E. Similarity of Subtrees【hash】

题意:

给你一棵树,问你有多少个组合的相似;

相似是a结点的子树和b结点的子树的每一层的结点数相等;

思路:

HASH来搞;

主要也没学过散列表,以及一个散列函数的构造;

其实看下面程序很简单,手跑案例就可以发现,每个结点有:a*pri^b,系数a就是在该节点下的b层结点个数。

暂时只理解到这个层面上,以后能用这个思想再用吧;

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef pair<double,double> PDD;
const int mod=1e9+7;
const double eps=1e-8;
const int inf=0x3f3f3f3f;
const double pi=acos(-1.0);
//LL powmod(LL a,LL b) {LL res=1;a%=mod; assert(b>=0); for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ULL pri;
map<ULL,LL>p;
VI g[100010];
ULL dfs(int x){
    int m=SZ(g[x]);
    ULL ans=1;
    for(int i=0;i<m;i++){
        ans+=dfs(g[x][i])*pri;
    }
    p[ans]++;
    return ans;
}
int main()
{
    pri=mod;
    map<ULL,LL>::iterator it;
    int n,u,v;
    cin>>n;
    for(int i=1;i<n;i++){
        cin>>u>>v;
        g[u].pb(v);
    }
    dfs(1);
    LL ans=0;
    for(it=p.begin();it!=p.end();it++){
        LL a=(*it).se;
        ans+=a*(a-1)/2;
    }
    cout<<ans<<endl;
    return 0;
}


原文地址:https://www.cnblogs.com/keyboarder-zsq/p/5934734.html