Similarity of Subtrees
Define the depth of a node in a rooted tree by applying the following rules recursively:
- The depth of a root node is 0.
- The depths of child nodes whose parents are with depth d
are 1
- .
Let )
be the number of nodes of d
.
You are given a rooted tree T
with j
.
Input
The input consists of a single test case.
N
1
The first line contains an integer N
(i
) The root node is numbered by 1. It is guaranteed that a given graph is a rooted tree, i.e. there is exactly one parent for each node except the node 1, and the graph is connected.
Output
Print the number of the pairs )
of the nodes such that the subtree with the root y
.
Sample Input 1
5 1 2 1 3 1 4 1 5
Output for the Sample Input 1
6
Sample Input 2
6 1 2 2 3 3 4 1 5 5 6
Output for the Sample Input 2
2
Sample Input 3
13 1 2 1 3 2 4 2 5 3 6 3 7 4 8 4 9 6 10 7 11 8 12 11 13
Output for the Sample Input 3
14
【分析】现在定义两棵树相似,仅当两棵树任意层次的节点数相等。然后给你一棵树,问你有多少棵子树是相似的。
类似字符串,我们可以将子树哈希,然后直接比较哈希值就可以了。
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int>pii; const int N = 1e5+5; const ll p = 9901; const ll mod = 1e9+7; const double eps = 1e-8; int n,m,k; ll has[N]; vector<int>edg[N]; map<ll,ll>mp; map<ll,ll>::iterator it; void dfs(int u,int fa){ has[u]=1; for(int v:edg[u]){ dfs(v,u); has[u]=(has[u]+has[v]*p)%mod; } mp[has[u]]++; } int main() { int u,v; scanf("%d",&n); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); edg[u].push_back(v); } dfs(1,0); ll ans=0; for(it =mp.begin();it!=mp.end();it++){ ans+=(it->second-1)*it->second/2; } printf("%lld\n",ans); return 0; }