zoukankan      html  css  js  c++  java
  • hackerrank HourRank 21 Hard Tree Isomorphism(无根树同构)

    传送门:https://www.hackerrank.com/contests/hourrank-21/challenges/tree-isomorphism

    题意是给你一颗树,求该树的子树中有多少棵不同构的树。

    同构的概念见题目或者自行百度

    由于是棵树,所以边数m为点数n-1,可以枚举2^m次方,用并查集(或者dfs判连通性)判断当前情况是否是一棵树,如果是就进行Hash判断是否重构。

    暂时不懂这Hash判重构的原理,先记录下用法:

    对于有根树,我只要从点开始跑一发hash,如果两棵树的hash值不同,说明两棵树不同构。如果是无根树,我需要判断从所有点开始跑的hash都要相同才说明两棵树不同构。所以对于无根树,我可以用set储存在该树的所有点得到的hash值,这个set就相当于该树的hash值。那么对于这题,我可以枚举所有边的情况后得到树,再得到该树的hash值,存进set中,最后set的size()+1就是答案(+1是只有一个点的情况)

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <string>
    #include <stack>
    #include <map>
    #include <set>
    #include <bitset>
    #define X first
    #define Y second
    #define clr(u,v); memset(u,v,sizeof(u));
    #define in() freopen("data","r",stdin);
    #define out() freopen("ans","w",stdout);
    #define Clear(Q); while (!Q.empty()) Q.pop();
    #define pb push_back
    using namespace std;
    typedef long long ll;
    typedef pair<int, int> pii;
    const int maxn = 20;
    const int INF = 0x3f3f3f3f;
    struct Edge
    {
        int v, to;
    } E[maxn*2];
    struct node
    {
        int u, v, flag;
    } P[maxn];
    int head[maxn], cnt;
    void addedge(int v, int u)
    {
        E[cnt].v = u, E[cnt].to = head[v];
        head[v] = cnt++;
    }
    
    #define mod 9973
    int h[maxn];//树的最大深度等于点数-1
    int vis[maxn];
    
    int Hash(int cur, int depth)//Hash部分
    {
        int Sum = h[depth];
        vis[cur] = 1;
        for(int i = head[cur]; ~i; i = E[i].to)
            if(!vis[E[i].v])
                Sum = (Sum + Hash(E[i].v, depth + 1) * h[depth]) % mod;
        vis[cur] = 0;
        return (Sum * Sum) % mod;
    }
    set <set<int> > S;
    int f[maxn], n, sum[maxn];
    
    void init()
    {
        for (int i = 0; i <= n; i++) f[i] = i, sum[i] = 1;
        clr(head, -1);
        cnt = 0;
    }
    int find(int x)
    {
        return f[x] == x ? x : f[x] = find(f[x]);
    }
    void mix(int x, int y)
    {
        int fx = find(x), fy = find(y);
        if (fx == fy) return ;
        f[fx] = fy;
        sum[fy] += sum[fx];
    }
    int ind = 1;
    void solve()
    {
        set <int> temp;//此时树的hash值
        init();
        for (int i = 1; i < n; i++)
            if (P[i].flag)
            {
                mix(P[i].v, P[i].u);
                addedge(P[i].v, P[i].u);
                addedge(P[i].u, P[i].v);
            }
        int Sum = 0, st = 1;
        for (int i = 1; i <= n; i++)//利用并查集判断是否是一棵树,Sum==1说明是点数大于1的树
            if (find(i) == i && sum[i] != 1)
            {
                st = i;
                Sum++;
            }
        if (Sum != 1) return ;
        for (int i = 1; i <= n; i++)
            if (find(i) == st)
            {
                int cur = Hash(i, 1);//cur 代表从cur这个点开始跑的hash值
                temp.insert(cur);
            }
        S.insert(temp);
    }
    void dfs(int cur)//2^(n-1)枚举所有情况
    {
        if (cur == n)
        {
            solve();
            return ;
        }
        P[cur].flag = 1;
        dfs(cur + 1);
        P[cur].flag = 0;
        dfs(cur + 1);
    }
    int main()
    {
        scanf("%d", &n);
        for(int i = 0; i <= n; ++i)
            h[i] = rand() % mod;
        for (int i = 1; i < n; i++)
            scanf("%d%d", &P[i].u, &P[i].v);
        dfs(1);
        printf("%d
    ", (int)S.size() + 1);
        return 0;
    }
  • 相关阅读:
    SQL server中自定义排序
    安装nodejs版本模块报错notsup Unsupported platform for n
    vue项目中一些标签直接放在<template>下会报错Failed to compile with 1 errors
    vue中使用element-ui出现Couldn't find preset "es2015" relative to directory
    解决两个相邻的span,或者input和button中间有间隙,在css中还看不到
    VsCode中代码折叠快捷键
    npm 操作代码
    vue项目打包成html,在本地点击直接能打开
    地图只显示部分区域,其他地区不显示
    vs里颜色显示块怎样显示
  • 原文地址:https://www.cnblogs.com/scaugsh/p/6935852.html
Copyright © 2011-2022 走看看