(2016 弱校联盟十一专场10.3) Similarity of Subtrees DFS + hash

2024-02-05 02:38

本文主要是介绍(2016 弱校联盟十一专场10.3) Similarity of Subtrees DFS + hash,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接
https://acm.bnu.edu.cn/v3/problem_show.php?pid=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 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.

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

题意:
输入一棵由n个点和n-1条边构成的树,求这个树中两棵相似的子树有多少对? 相似的子树:要求在相同的深度,两颗子树的在这一层的节点数相同;

分析:
要找出所有的相似的子树,n<=100000,所以我们不可能两两比较。但是我们可以表示出所有子树,然后在计算结果就可以了。

思路:深搜,hash表示每一个点为子树时的子树状态;
这里写图片描述

第三组样例:对图上每个点,给一个标识p^d d为这个点的深度,那么每个点的子树状态就可以用子树上所有项的和表示,如2号节点p^4+2p^3+2p^2+p 3号节点p^4+2p^3+2p^2+p 它们的多项式相同,为了方便用map映射统计,可以给p赋一个值,为了减小冲突可以取一个较大的质数,这就是hash;

AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <cmath>
#include <vector>
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()
{LL n,u,v;while(scanf("%lld",&n)!=EOF){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;
}

这篇关于(2016 弱校联盟十一专场10.3) Similarity of Subtrees DFS + hash的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/679533

相关文章

学习hash总结

2014/1/29/   最近刚开始学hash,名字很陌生,但是hash的思想却很熟悉,以前早就做过此类的题,但是不知道这就是hash思想而已,说白了hash就是一个映射,往往灵活利用数组的下标来实现算法,hash的作用:1、判重;2、统计次数;

hdu1043(八数码问题,广搜 + hash(实现状态压缩) )

利用康拓展开将一个排列映射成一个自然数,然后就变成了普通的广搜题。 #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#include<stdlib.h>#include<ctype.h>#inclu

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

hdu1496(用hash思想统计数目)

作为一个刚学hash的孩子,感觉这道题目很不错,灵活的运用的数组的下标。 解题步骤:如果用常规方法解,那么时间复杂度为O(n^4),肯定会超时,然后参考了网上的解题方法,将等式分成两个部分,a*x1^2+b*x2^2和c*x3^2+d*x4^2, 各自作为数组的下标,如果两部分相加为0,则满足等式; 代码如下: #include<iostream>#include<algorithm

usaco 1.2 Milking Cows(类hash表)

第一种思路被卡了时间 到第二种思路的时候就觉得第一种思路太坑爹了 代码又长又臭还超时!! 第一种思路:我不知道为什么最后一组数据会被卡 超时超了0.2s左右 大概想法是 快排加一个遍历 先将开始时间按升序排好 然后开始遍历比较 1 若 下一个开始beg[i] 小于 tem_end 则说明本组数据与上组数据是在连续的一个区间 取max( ed[i],tem_end ) 2 反之 这个

hdu 2489 (dfs枚举 + prim)

题意: 对于一棵顶点和边都有权值的树,使用下面的等式来计算Ratio 给定一个n 个顶点的完全图及它所有顶点和边的权值,找到一个该图含有m 个顶点的子图,并且让这个子图的Ratio 值在所有m 个顶点的树中最小。 解析: 因为数据量不大,先用dfs枚举搭配出m个子节点,算出点和,然后套个prim算出边和,每次比较大小即可。 dfs没有写好,A的老泪纵横。 错在把index在d

uva 10029 HASH + DP

题意: 给一个字典,里面有好多单词。单词可以由增加、删除、变换,变成另一个单词,问能变换的最长单词长度。 解析: HASH+dp 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#inc

poj 3050 dfs + set的妙用

题意: 给一个5x5的矩阵,求由多少个由连续6个元素组成的不一样的字符的个数。 解析: dfs + set去重搞定。 代码: #include <iostream>#include <cstdio>#include <set>#include <cstdlib>#include <algorithm>#include <cstring>#include <cm

整数Hash散列总结

方法:    step1  :线性探测  step2 散列   当 h(k)位置已经存储有元素的时候,依次探查(h(k)+i) mod S, i=1,2,3…,直到找到空的存储单元为止。其中,S为 数组长度。 HDU 1496   a*x1^2+b*x2^2+c*x3^2+d*x4^2=0 。 x在 [-100,100] 解的个数  const int MaxN = 3000

POJ 1198 双广+Hash

此题采用双广可从bfs的O(16^8)降低到O(2*16^4); 坐标0-7,刚好3位存储, 需要24位存储四个坐标(x,y),也就是[0,2^24) 。 很好的一题。 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import