bzoj 4337[BJOI2015]树的同构 - 括号序列
4337: BJOI2015 树的同构
Time Limit: 10 Sec Memory Limit: 256 MBDescription
树是一种很常见的数据结构。
我们把N个点,N-1条边的连通无向图称为树。
若将某个点作为根,从根开始遍历,则其它的点都有一个前驱,这个树就成为有根树。
对于两个树T1和T2,如果能够把树T1的所有点重新标号,使得树T1和树T2完全相
同,那么这两个树是同构的。也就是说,它们具有相同的形态。
现在,给你M个有根树,请你把它们按同构关系分成若干个等价类。
Input
第一行,一个整数M。
接下来M行,每行包含若干个整数,表示一个树。第一个整数N表示点数。接下来N
个整数,依次表示编号为1到N的每个点的父亲结点的编号。根节点父亲结点编号为0。
Output
输出M行,每行一个整数,表示与每个树同构的树的最小编号。
Sample Input
4
4 0 1 1 2
4 2 0 2 3
4 0 1 1 1
4 0 1 2 3
4 0 1 1 2
4 2 0 2 3
4 0 1 1 1
4 0 1 2 3
Sample Output
1
1
3
1
1
3
1
HINT
【样例解释】
编号为1, 2, 4 的树是同构的。编号为3 的树只与它自身同构。
100% 的数据中,1 ≤ N, M ≤ 50。
对于一颗有根树,可以用括号序列唯一的表示
将所有儿子的子树的括号序列按从小到大排序,在最外面再用一个括号括起来
就是这颗子树的括号序列。
一颗无根树的重心最多有两个,我们以重心为根,取括号序列更大的一个就可以一一对应了
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #define LL long long 6 7 using namespace std; 8 9 const int MAXN = 60, MAXM = 60; 10 11 int N, M; 12 13 int size[MAXN]; 14 int head[MAXN]; 15 int vis[MAXN]; 16 int cnt = 0; 17 18 inline LL read() 19 { 20 LL x = 0, w = 1; char ch = 0; 21 while(ch < '0' || ch > '9') { 22 if(ch == '-') { 23 w = -1; 24 } 25 ch = getchar(); 26 } 27 while(ch >= '0' && ch <= '9') { 28 x = x * 10 + ch - '0'; 29 ch = getchar(); 30 } 31 return x * w; 32 } 33 34 struct edge { 35 int v; 36 int next; 37 } g[MAXN * MAXN]; 38 39 int f[MAXN]; 40 int mx = 0; 41 42 string h[MAXM]; 43 void addedge(int u, int v) 44 { 45 g[++cnt].v = v; 46 g[cnt].next = head[u]; 47 head[u] = cnt; 48 } 49 50 void getroot(int x) 51 { 52 vis[x] = 1; 53 int minn = 0; 54 size[x] = 1; 55 for(int j = head[x]; j; j = g[j].next) { 56 int to = g[j].v; 57 if(!vis[to]) { 58 getroot(to); 59 size[x] += size[to]; 60 } 61 minn = max(size[to], minn); 62 } 63 minn = max(minn, N - size[x]); 64 f[x] = minn; 65 mx = min(minn, mx); 66 } 67 68 string DFS(int x) 69 { 70 // cout<<x<<endl; 71 vis[x] = 1; 72 int tot = 0; 73 string t[MAXN]; 74 string temp = ""; 75 temp += "("; 76 for(int j = head[x]; j; j = g[j].next) { 77 int to = g[j].v; 78 if(!vis[to]) { 79 t[tot++] = DFS(to); 80 } 81 } 82 sort(t, t + tot); 83 for(int i = 0; i < tot; i++) { 84 temp += t[i]; 85 } 86 temp += ")"; 87 return temp; 88 } 89 90 int main() 91 { 92 M = read(); 93 for(int i = 1; i <= M; i++) { 94 N = read(); 95 cnt = 0; 96 memset(head, 0, sizeof head); 97 memset(f, 0, sizeof f); 98 memset(vis, 0, sizeof vis); 99 memset(size, 0, sizeof size); 100 for(int j = 1; j <= N; j++) { 101 int l = read(); 102 if(l) { 103 addedge(j, l); 104 addedge(l, j); 105 } 106 } 107 mx = 1e9; 108 getroot(1); 109 for(int j = 1; j <= N; j++) { 110 //cout<<f[j]<<" "; 111 if(f[j] == mx) { 112 memset(vis, 0, sizeof vis); 113 h[i] = max(h[i], DFS(j)); 114 } 115 } 116 } 117 for(int i = 1; i <= M; i++) { 118 for(int j = 1; j <= i; j++) { 119 if(h[j] == h[i]) { 120 printf("%d\n", j); 121 break; 122 } 123 } 124 } 125 return 0; 126 } 127 128 /* 129 130 7 131 6 0 1 5 1 1 5 132 6 2 4 4 0 4 1 133 6 0 1 6 1 3 1 134 6 6 0 1 2 2 2 135 6 5 5 0 6 3 2 136 6 0 6 2 6 3 1 137 6 2 6 2 5 3 0 138 139 140 141 */