ZOJ 3602 Count the Trees 树的同构 (哈希)

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4705

题意:给出两棵二叉树A和B,问分别处于A中的子树a和处于B中的子树b结构相同的有多少对。

思路:哈希的想法,不同的数字对应的是不同的结构,比如1代表着单独的叶子结点,2代表着有左子树是叶子结点而没有右子树的子树...每出现一种新的子树情形就记录下来,记录的方式是用dfs回溯过程中判断左子树和右子树组成的子树是否出现过(用pair记录子树的情况,也就是左右子树,两个map,第一个map表示子树的pair与它的标号的映射,第二个map表示每种标号出现的次数)。

代码:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <ctype.h>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
#define eps 1e-8
#define INF 0x7fffffff
#define maxn 100005
#define PI acos(-1.0)
#define seed 31//131,1313
typedef long long LL;
typedef unsigned long long ULL;
using namespace std;
int top=0;
map < pair < int , int > , int > M;
map < int , LL > N ;
int tree_a[maxn][2],tree_b[maxn][2],a[maxn],b[maxn];
LL ans;
void dfs_a(int u)
{
    pair < int , int > p;
    int left,right;
    left=tree_a[u][0],right=tree_a[u][1];
    if(left!=-1)
        dfs_a(left);
    if(right!=-1)
        dfs_a(right);
    if(left==-1)
        p.first=-1;
    else p.first=a[left];
    if(right==-1)
        p.second=-1;
    else p.second=a[right];
    if(M.find(p)==M.end())
    {
        M[p]=top;
        a[u]=top;
        N[top]=1;
        top+=3;
    }
    else
    {
        a[u]=M[p];
        N[M[p]]++;
    }
}
void dfs_b(int u)
{
    pair <int ,int > p ;
    int left=tree_b[u][0],right=tree_b[u][1];
    if(left!=-1)
        dfs_b(left);
    if(right!=-1)
        dfs_b(right);
    if(left==-1)
        p.first=-1;
    else p.first=b[left];
    if(right==-1)
        p.second=-1;
    else p.second=b[right];
    if(M.find(p)!=M.end())
    {
        ans+=N[M[p]];
        b[u]=M[p];
    }
}
void init()
{
    top=0;
    ans=0;
    N.clear();
    M.clear();
    for(int i=0;i<=100000;i++)
        a[i]=-2,b[i]=-2;
}
int main()
{
    int T,n,m;
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
            scanf("%d%d",&tree_a[i][0],&tree_a[i][1]);
        for(int i=1; i<=m; i++)
            scanf("%d%d",&tree_b[i][0],&tree_b[i][1]);
        dfs_a(1);
        dfs_b(1);
        printf("%lld\n",ans);
    }
    return 0;
}
时间: 2024-11-03 21:00:24

ZOJ 3602 Count the Trees 树的同构 (哈希)的相关文章

ZOJ 3602 Count the Trees

题意: 两棵树(10^5个节点)  问其中有多少对子树是同构的 思路: 树的同构一般使用hash来判断 hash函数为1.val=A   2.val = (val*P)^Soni%Q  其中Soni为第i个子树的hash值  3.val=val*B%Q 注意Son值应该排序  (本题因为左右子树是区分开的  因此不用排序) 代码: #include<cstdio> #include<iostream> #include<cstring> #include<stri

zjuoj 3602 Count the Trees

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3602 Count the Trees Time Limit: 2 Seconds      Memory Limit: 65536 KB A binary tree is a tree data structure in which each node has at most two child nodes, usually distinguished as "left&

ZOJ 1610 Count the Colors (线段树区间更新)

题目链接 题意 : 一根木棍,长8000,然后分别在不同的区间涂上不同的颜色,问你最后能够看到多少颜色,然后每个颜色有多少段,颜色大小从头到尾输出. 思路 :线段树区间更新一下,然后标记一下,最后从头输出. //ZOJ 1610 #include <cstdio> #include <cstring> #include <iostream> using namespace std ; int p[8010*4],lz[8010*4] ,hashh[8010*4],has

ZOJ--3602--Count the Trees【DFS+Hash】树的同构

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3602 题意:给出一棵有n个节点的二叉树和一棵有m个节点的二叉树,给出每个节点的左右子树信息,问这两棵树有几个相同的子树. 思路:树的同构,比赛时没想法,赛后看的别人的解题报告.实际上是给每个节点的左右子树一个哈希值,不用像字符串哈希那么麻烦,直接给每个子树一个数字标记就行了,用map映射每个节点的左子树和右子树信息对应一个标记值,用DFS给两棵树的每个节点都赋一个哈

4292: Count the Trees(树hash)

4292: Count the Trees  时间限制(普通/Java):2000MS/6000MS     内存限制:65536KByte总提交: 15            测试通过:6 描述 A binary tree is a tree data structure in which each node has at most two child nodes, usually distinguished as "left" and "right". A su

zoj 1610 Count the Colors

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=610 先用线段树维护区间颜色的覆盖,然后在把区间的颜色映射到数组,再从数组统计颜色. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define maxn 100000 5 using namespace std; 6 7 int n; 8 int min1; 9

UVa 10007 &amp; hdu 1131 Count the Trees (卡特兰数)

Count the Trees Time Limit:3000MS    Memory Limit:0KB     64bit IO Format:%lld & %llu SubmitStatus Description  Count the Trees  Another common social inability is known as ACM (Abnormally Compulsive Meditation). This psychological disorder is somewh

ZOJ 2859 二维线段树

思路:自己写的第二发二维线段树1A,哈哈,看来对二维的push操作比较了解了:但是还没遇到在两个线段树中同时进行push操作的,其实这题我是想在x维和y维同时进行push操作的,但是想了好久不会,然后看到这题又给出10秒,然后想想在x维线段直接单点查询肯定也过了,然后在第二维就只有pushup操作,在第一维线段树没有pushup操作.要是在第一维也有pushup操作的话,那就不用单点查询那么慢了.不过也A了,想找题即在二维同时进行pushup和pushdown操作的. #include<iost

SDUT 3340 数据结构实验之二叉树一:树的同构

数据结构实验之二叉树一:树的同构 Time Limit: 1000MS Memory Limit: 65536KB Submit Statistic Problem Description 给定两棵树T1和T2.如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是"同构"的.例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A.B.G的左右孩子互换后,就得到另外一棵树.而图2就不是同构的. 图1 图2 现给定两棵树,请你判断它们是否是同构的. Input 输入数据包含