隐藏
「BJOI2015」树的同构 - 无根树的同构 | Bill Yang's Blog

路终会有尽头,但视野总能看到更远的地方。

0%

「BJOI2015」树的同构 - 无根树的同构

题目大意

提供若干棵无根树,求每一棵树与哪一棵树同构?输出最小编号的树。


初步想法

然而我们已经做过几道树的同构的题了。
其实Hash是解决所有树同构问题的通法,虽然是非完美算法。
另外其实这道题是无根树,题面在坑爹,所以说和仔细地检查差不多,需要求出重心。


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
typedef unsigned long long LL;
inline const int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
const int maxn=105;
LL n,Size[maxn],cnt=0,tot=0,Hash[maxn],Maxson[maxn],a[maxn],Min=0x7fffffff/2,Min1,Min2;
vector<int>edges[maxn];
void AddEdge(int x,int y) {
edges[x].push_back(y);
}
bool cmp1(const int& a,const int& b) {
return Size[a]<Size[b]||(Size[a]==Size[b]&&Hash[a]<Hash[b]);
}
void Dfs1(int Now,int father) {
Size[Now]=1;
for(int i=0; i<edges[Now].size(); i++) {
int Next=edges[Now][i];
if(Next==father)continue;
Dfs1(Next,Now);
Size[Now]+=Size[Next];
}
cnt=0;
for(int i=0; i<edges[Now].size(); i++) {
int Next=edges[Now][i];
if(Next==father)continue;
a[++cnt]=Next;
}
sort(a+1,a+cnt+1,cmp1);
a[cnt+1]=father;
for(int i=0; i<edges[Now].size(); i++)edges[Now][i]=a[i+1];
Hash[Now]=Size[Now];
for(int i=0; i<edges[Now].size(); i++) {
int Next=edges[Now][i];
if(Next==father)continue;
Hash[Now]=Hash[Now]*99995999^Hash[Next];
}
}
void Find_Core(int Now,int father) {
Size[Now]=1;
for(int i=0; i<edges[Now].size(); i++) {
int Next=edges[Now][i];
if(Next==father)continue;
Find_Core(Next,Now);
Size[Now]+=Size[Next];
Maxson[Now]=max(Maxson[Now],Size[Next]);
}
Maxson[Now]=max(Maxson[Now],n-Size[Now]);
if(Maxson[Now]<Min) {
Min=Maxson[Now];
Min1=Now;
Min2=0;
} else if(Maxson[Now]==Min)Min2=Now;
}
void Clear() {
memset(Maxson,0,sizeof(Maxson));
Min=0x7fffffff/2;
Min1=Min2=0;
for(int i=1; i<=n; i++)edges[i].clear();
cnt=0;
memset(a,0,sizeof(a));
memset(Hash,0,sizeof(Hash));
}
int t;
LL HashAll[maxn][5];
int main() {
t=Get_Int();
for(int i=1; i<=t; i++) {
Clear();
n=Get_Int();
for(int j=1; j<=n; j++) {
int x=Get_Int();
if(x==0)continue;
AddEdge(x,j);
AddEdge(j,x);
}
Find_Core(1,0);
Dfs1(Min1,0);
HashAll[i][1]=Hash[Min1];
if(Min2) {
Dfs1(Min2,0);
HashAll[i][2]=Hash[Min2];
} else HashAll[i][2]=-1;
}
for(int i=1; i<=t; i++)
for(int j=1; j<=t; j++)
if(HashAll[i][1]==HashAll[j][1]||(HashAll[i][2]!=-1&&HashAll[i][2]==HashAll[j][1])||(HashAll[j][2]!=-1&&HashAll[i][1]==HashAll[j][2])||(HashAll[i][2]!=-1&&HashAll[j][2]&&HashAll[i][2]==HashAll[j][2])) {
printf("%d\n",j);
break;
}
return 0;
}
姥爷们赏瓶冰阔落吧~