您的位置:首页 > 其它

zoj 3602 Count the Trees 树的同构

2012-08-06 00:54 441 查看
/*
二叉树的同构
把每棵子树映射为一个整数
如节点n的左右孩子为L,R,那么取子树L对应的整数Ln
子树R对应的整数Rn,把pair(Ln,Rn)对应为一个整数就是
当前子树的映射
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<set>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=100009*4;
int n[2];
struct Node
{
int l,r,f;//左、右、父
}node[2][maxn];
int deg[maxn],hash[2][maxn],num[2][maxn];
//deg表示节点有多少棵子树
//hash[i][j]表示第i棵树中,以节点j为根的子树对应的哈希值
//num[i][j]表示第i棵树中,哈希值为j的子树有多少棵
long long ans;
map<pair<int,int>,int> my;
void init()
{
scanf("%d%d",&n[0],&n[1]);
for(int j=0;j<2;j++)
for(int i=1;i<=n[j];i++)
{
scanf("%d%d",&node[j][i].l,&node[j][i].r);
if(node[j][i].l!=-1)
node[j][node[j][i].l].f=i;
if(node[j][i].r!=-1)
node[j][node[j][i].r].f=i;
}
}
void bfs(int t)
{
int now,L,R;
queue<int> q;
deg[0]=3;
for(int i=1;i<=n[t];i++)
{
deg[i]=(node[t][i].l>-1)+(node[t][i].r>-1);
if(deg[i]==0)
{
hash[t][i]=0;
q.push(i);
}
}
while(!q.empty())
{

now=q.front();q.pop();
L=-1;//左子树的hash值
if(node[t][now].l>-1)
L=hash[t][node[t][now].l];
R=-1;//右子树的hash值
if(node[t][now].r>-1)
R=hash[t][node[t][now].r];
pair<int,int> pi=make_pair(L,R);//当前子树的特征值
if(my[pi]==0) my[pi]=my.size()+1;//my[pi]当前子树的哈希值
num[t][my[pi]]++;
hash[t][now]=my[pi];
if(t)ans+=num[!t][my[pi]];
//如果的第二棵树,加上第一棵树中hash值和当前子树hash值相同的子树的个数
deg[node[t][now].f]--;
if(deg[node[t][now].f]==0)
q.push(node[t][now].f);
}
}
void solve()
{
my.clear();
node[0][1].f=node[1][1].f=0;
memset(num,0,sizeof(num));
ans=0;
bfs(0);
bfs(1);
cout<<ans<<endl;
}
int main()
{
int ca;
scanf("%d",&ca);
while(ca--)
{
init();
solve();
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: