luogu P5043 【模板】树同构([BJOI2015]树的同构)

https://www.luogu.com.cn/problem/P5043

突然发现之前自己的技能树点得有点乱

可以直接用最小表示法求出树的括号序列来判断是否同构

根节点取重心即可,如果有两个,取字典序更小的那个

时间复杂度\(O(n^2m)\)

code:

#include<bits/stdc++.h>
#define N 250
using namespace std;
int siz[N], msiz[N], n, t;
vector<int> g[N];
void findrt(int u, int fa) {
    siz[u] = 1; msiz[u] = 0;
    for(int v : g[u]) {
        if(v == fa) continue;
        findrt(v, u); siz[u] += siz[v];
        msiz[u] = max(msiz[u], siz[v]);
    }
    msiz[u] = max(msiz[u], n - siz[u]);
}
string f[N], ls[N], ha[N];
void dfs(int u, int fa) {
    f[u] = "0";
    int gs = 0;
    for(int v : g[u]) {
        if(v == fa) continue;
        dfs(v, u);
    }
    for(int v : g[u]) {
        if(v == fa) continue;
        ls[++ gs] = f[v];
    }
    sort(ls + 1, ls + 1 + gs);
    for(int i = 1; i <= gs; i ++) f[u] = f[u] + ls[i];
    f[u] = f[u] + "1";
}
int main() {
   // freopen("a.out","w",stdout);
    scanf("%d", &t);
    for(int id = 1; id <= t; id ++) {
        scanf("%d", &n);
        for(int i = 1; i <= n; i ++) g[i].clear();
        for(int i = 1; i <= n; i ++) {
            int x;
            scanf("%d", &x);
            if(x) g[i].push_back(x), g[x].push_back(i);
        }

        findrt(1, 0);
        int rt = 1;
        for(int i = 1; i <= n; i ++) if(msiz[i] < msiz[rt]) rt = i;
        ha[id] = "3";
        for(int i = 1; i <= n; i ++) if(msiz[i] == msiz[rt]) {
            dfs(i, 0);
            ha[id] = min(ha[id], f[i]);
        }        

        for(int i = 1; i <= id; i ++) if(ha[i] == ha[id]) {//printf("** %d %d\n", id, i);
            printf("%d\n", i); break;
            
        }
    }
    return 0;
}
posted @ 2022-02-16 15:29  lahlah  阅读(51)  评论(0编辑  收藏  举报