zoukankan      html  css  js  c++  java
  • bzoj 4337[BJOI2015]树的同构

    4337: BJOI2015 树的同构

    Time Limit: 10 Sec  Memory Limit: 256 MB

    Description

    树是一种很常见的数据结构。
    我们把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

    Sample Output

    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
    ", 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 */
    View Code
     
     
     
  • 相关阅读:
    ext2 / ext3 结构分析
    怎么解决TortoiseSVN文件夹图标不显示?
    CVS Update后,p u 各代表什么意思? 颜色代表什么意思?
    Oracle Purge和drop的区别
    oracle怎样删除回收站里面的表
    oracle 查询所有表 和视图表
    PLSQL 数据中去掉 字段有空格 回车 换行
    plsql update 字段值 前面增加 字符
    function 通过商品编号 获取商品名称
    远程连接后 Xshell 怎么显示桌面 命令
  • 原文地址:https://www.cnblogs.com/wuenze/p/8598021.html
Copyright © 2011-2022 走看看