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; }