Problem E Similarity of Subtrees

来源:互联网 发布:潍坊行知学校复读 编辑:程序博客网 时间:2024/05/21 14:01

题目

Problem E Similarity of Subtrees
Input: Standard Input Time Limit: See AtCoder
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 d + 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 except 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 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
15
Output for the Sample Input 3
14

题目分析

这道题肯定是使用dfs从叶子节点向根推,其实就是递归的思想,但是相当于对于每个节点求一次值,然后对于这个值进行hash,这样就可以判断相似的数究竟有多少,然后迭代器跑一边求值即可。

#include <map>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int maxn = 1e5+100;const int mod = 1e9+7;typedef unsigned long long ULL;ULL pri;int head[maxn], tot;map <ULL, int> M;struct Edge{    int to, next;}e[maxn];void addedge(int from, int to){    e[tot].to = to;    e[tot].next = head[from];    head[from] = tot++;}ULL dfs(int u){    ULL ans = 1;    for(int i = head[u]; i != -1; i = e[i].next){        ans += dfs(e[i].to)*pri;    }    M[ans]++;    return ans;}void init(){    tot = 0;    M.clear();    memset(head, -1, sizeof(head));}int main(){    pri = mod;    int n;    while(scanf("%d", &n) != EOF){        init();        int from, to;        for(int i = 1; i < n; i++){            scanf("%d%d", &from, &to);            addedge(from, to);        }        dfs(1);        ULL ans = 0;        for(map <ULL,int>::iterator it = M.begin(); it != M.end(); it++){            ULL cnt = it->second;            ans += cnt*(cnt-1)/2;        }        cout << ans << endl;    }    return 0;}
0 0