2016 Weak School Alliance 11 session 10.3 --- Similarity of Subtrees (Deep Search + hash, ing), deep search and wide search
Question Link
Https://acm.bnu.edu.cn/v3/problem_show.php? Pid = 1, 52310
Problem description
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 S (T, d) be the number of nodes of T with depth d. two rooted trees T and T' are similar if and only if S (T, d) equals S (t', d) for all non-negative integer d. you are given a rooted tree T with N nodes. the nodes of T are numbered from 1 to N. node 1 is the root node of T. let Ti be the rooted subtree of T whose root is node I. your task is to write a program which calculates the number of pairs (I, j) such that Ti and Tj are similar and I <j.
Input
The input consists of a single test case. N a1 b1... AN −1 bN −1 The first line contains an integer N (1 ≤ N ≤ 100,000), which is the number of nodes in a tree. the following N −1 lines give information of branches: the I-th line of them contains ai and bi, which indicates that a node ai is a parent of a node bi. (1 ≤ ai, bi ≤ N, ai ≤ = bi) 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 should t the node 1, and the graph is connected.
Output
Print the number of the pairs (x, y) of the nodes such that the subtree with the root x and the subtree with the root y are similar and x <y. 14
Sample Input1
5
1 2
1 3
1 4
1 5
Output for the Sample Input 1
6
Sample Input2
6
1 2
2 3
3 4
1 5
5 6
Output for the Sample Input 2
2
Sample Input3
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
Question: How many pairs of two similar Subtrees in a tree composed of n points and n-1 sides? Similar subtree: it must be in the same depth, and the number of nodes at the same layer of the two subtree is the same;
Idea: Deep Search. hash indicates the status of the subtree when each vertex is a subtree;
Example 3: For each vertex on the graph, Mark p ^ d as the depth of the vertex, then, the subtree state of each vertex can be expressed by the sum of all items in the subtree, for example, node 2 p ^ 4 + 2 p ^ 3 + 2 p ^ 2 + p 3 p ^ 4 + 2 p ^ 3 + 2 p ^ 2 + p has the same polynomial, to facilitate map ing statistics, you can assign a value to p. To reduce the conflict, you can obtain a large prime number, which is hash;
The Code is as follows:
#include <iostream>#include <stdio.h>#include <queue>#include <string.h>#include <vector>#include <map>#include <string>#include <set>using namespace std;typedef long long LL;const LL maxn=1e6+10,p=9901,mod=1e9+7;vector<LL>G[maxn];LL hash_v[maxn];map<LL,LL>mp;map<LL,LL>::iterator it;void dfs(LL u){ hash_v[u]=1; for(LL i=0; i<G[u].size(); i++) { LL v=G[u][i]; dfs(v); hash_v[u]=(hash_v[u]+hash_v[v]*p)%mod; } mp[hash_v[u]]++;}int main(){ ///freopen("in.txt","r",stdin); LL n; LL u,v; while(scanf("%lld",&n)!=-1) { for(LL i=0; i<=n; i++) G[i].clear(); mp.clear(); for(LL i=1; i<n; i++) { scanf("%lld%lld",&u,&v); G[u].push_back(v); } dfs(1); LL ans=0; for(it=mp.begin(); it!=mp.end(); it++) ans+=it->second*(it->second-1)/2; printf("%lld\n",ans); } return 0;}