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

    嘟嘟嘟


    判断树的同构的方法就是树上哈希。


    如果树是一棵有根树,那么只要从根节点出发dfs,每一个节点的哈希值等于按传统方式算出来的子树的哈希值的结果。需要注意的是,算完子树的哈希值后要先排序再加起来,因为交换两棵子树对于判断同构不影响。


    对于无根树,我们应该选一个点,满足树的标号改变后树的形态没有变。所以就选重心好了。重心可能有两个(一条边的两个端点上),所以分别求一遍哈希取max(min)即可。


    结果这题卡我的哈希(可能是我太菜了),最后写成ret = ((ret * base) | t[i]) % mod才过,自然溢出都不出行。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<stack>
    #include<queue>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    typedef long long ll;
    typedef unsigned long long ull;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const ull base = 19260817;
    const ull mod = 1e9 + 7;
    const int maxn = 55;
    inline ll read()
    {
      ll ans = 0;
      char ch = getchar(), last = ' ';
      while(!isdigit(ch)) last = ch, ch = getchar();
      while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
      if(last == '-') ans = -ans;
      return ans;
    }
    inline void write(ll x)
    {
      if(x < 0) x = -x, putchar('-');
      if(x >= 10) write(x / 10);
      putchar(x % 10 + '0');
    }
    
    int m, n;
    struct Edge
    {
      int nxt, to;
    }e[maxn << 1];
    int head[maxn], ecnt = -1;
    In void addEdge(int x, int y)
    {
      e[++ecnt] = (Edge){head[x], y};
      head[x] = ecnt;
    }
    
    int siz[maxn], dp[maxn], G = INF;
    In void dfs1(int now, int _f)
    {
      siz[now] = 1; dp[now] = 0;
      for(int i = head[now], v; ~i; i = e[i].nxt)
        {
          if((v = e[i].to) == _f) continue;
          dfs1(v, now);
          siz[now] += siz[v];
          dp[now] = max(dp[now], siz[v]);
        }
      dp[now] = max(dp[now], n - siz[now]);
      G = min(G, dp[now]);
    }
    
    ull ans[maxn];
    In ull dfs2(int now, int _f)
    {
      ull ret = 1343247397;
      vector<ull> tp;
      for(int i = head[now], v; ~i; i = e[i].nxt)
        {
          if((v = e[i].to) == _f) continue;
          tp.push_back(dfs2(v, now));
        }
      sort(tp.begin(), tp.end());
      for(int i = 0; i < (int)tp.size(); ++i) ret = ((ret * base) ^ tp[i]);
      return ret;
    }
    
    In void init()
    {
      Mem(head, -1); ecnt = -1;
      G = INF;
    }
    
    int main()
    {
      //freopen("2.in", "r", stdin);
      //freopen("ha.out", "w", stdout);
      m = read();
      for(int i = 1; i <= m; ++i)
        {
          init();
          n = read();
          for(int j = 1; j <= n; ++j)
    	{
    	  int x = read();
    	  if(x) addEdge(x, j), addEdge(j, x);
    	}
          dfs1(1, 0);
          for(int j = 1; j <= n; ++j)
    	if(dp[j] == G) ans[i] = max(ans[i], dfs2(j, 0));
        }
      for(int i = 1; i <= m; ++i)
        for(int j = 1; j <= i; ++j)
          if(ans[i] == ans[j]) {write(j), enter; break;}
      return 0;
    }
    
  • 相关阅读:
    ZOJ 3332 Strange Country II
    ZOJ 3331 Process the Tasks(双塔DP)
    ZOJ 3326 An Awful Problem(模拟)
    HDU 1796 How many integers can you find(容斥原理)
    HDU 4059 The Boss on Mars(容斥原理)
    HDU 4135 Co-prime(容斥原理)
    HDU 5677 ztr loves substring(回文串加多重背包)
    CodeForces 668B Little Artem and Dance
    CodeForces 667A Pouring Rain
    Java实现 LeetCode 764 最大加号标志(暴力递推)
  • 原文地址:https://www.cnblogs.com/mrclr/p/10551294.html
Copyright © 2011-2022 走看看