zoukankan      html  css  js  c++  java
  • BZOJ 4337 树的同构

        很明显,这应该是一道模版题(因为我很快就在一本书上找到了这道题的模版),不过令我比较奇怪的大概是有根树和无根树的概念,以及在这道题目中根有卵用吗? (看来树这一块的知识还是要补一下)。 树的同构很明显应该是用hash来判断的,当然了,不同的人设计的hash函数不同了。这道题正确的应该是要在树的重心上面跑这道题的模版,(如果你要问我树的重心是啥,我只能跟你说,如果我知道的话,下面这份代码就不会把几乎所有的点都跑一次了,但是由于N<=50,M <= 50 很明显这样跑完还是很快的,事实证明也只跑了32毫秒,但本着求真务实的心态,找个时间再补下树吧!)。很明显,尽管两棵树的形态完全相同,但如果从不同的节点开始跑这个模版,所得的hash值也会不同。所以正确的是要在几乎唯一的重心上跑(据说,一棵有根树的重心最多有两个)。加油吧!相信自己。(我是一条可耻的源程狗)。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<vector>
      4 #include<set>
      5 #include<map>
      6 #include<algorithm>
      7 #define ull unsigned long long
      8 #define magic 107ull
      9 #define rep(i,j,k) for(int i = j; i <= k; i++)
     10 #define maxn 60
     11 using namespace std;
     12 
     13 int read()
     14 {
     15     int s = 0, t = 1; char c = getchar();
     16     while( !isdigit(c) ){
     17         if( c == '-' ) t = -1; c = getchar();
     18     }
     19     while( isdigit(c) ){
     20         s = s * 10 + c -'0'; c = getchar();
     21     }
     22     return s * t;
     23 }
     24 
     25 ull pow(ull key,int n)
     26 {
     27     ull ret = 1ull;
     28     while( n ){
     29        if( n & 1 ){
     30              ret *= key;
     31        }
     32        key *= key, n >>= 1;
     33     }
     34     return ret;
     35 }
     36 
     37 struct hash{
     38 int length; ull key;
     39 
     40 hash(): length(0), key(0) {}
     41 hash(char c): length(1), key(c) {}
     42 hash(int l,ull key): length(l), key(key) {}
     43 };
     44 vector<hash> childs[maxn];
     45 
     46 bool operator < (const hash&a, const hash&b){
     47     return a.key < b.key;
     48 }
     49 
     50 hash operator + (const hash&a, const hash& b){
     51     return hash(a.length+b.length,a.key*pow(magic,b.length)+b.key);
     52 }
     53 
     54 void operator += (hash&a,const hash&b){
     55     a = a + b;
     56 }
     57 
     58 vector<int> g[maxn];
     59 
     60 hash dfs(int pre,int now)
     61 {
     62     hash ret;
     63     childs[now].clear(); int s = g[now].size();
     64     rep(i,0,s-1){
     65         int to = g[now][i];
     66         if( to == pre ) continue;
     67         childs[now].push_back(dfs(now,to));
     68     }
     69     sort(childs[now].begin(),childs[now].end());
     70     for(vector<hash>::iterator iter = childs[now].begin(); iter != childs[now].end(); iter++){
     71         ret += *iter;
     72     }
     73     ret = '(' +  ret + ')';
     74     return ret;
     75     
     76 }
     77 
     78 ull gethash(int root)
     79 {
     80     return dfs(-1,root).key;
     81 }
     82 
     83 set<ull> s;
     84 map<ull,int> mp; 
     85 
     86 void clear()
     87 {
     88     rep(i,1,maxn) g[i].clear();
     89 }
     90 
     91 int main()
     92 {
     93     int n = read();
     94     rep(i,1,n){
     95         clear(); s.clear();
     96         int m = read();
     97         rep(j,1,m){
     98             int x = read();
     99             if( x ) g[j].push_back(x), g[x].push_back(j);
    100         }
    101         bool ok = 0;
    102         rep(j,1,m){
    103             ull key = gethash(j);
    104             if( mp[key] ) {
    105                 printf("%d
    ", mp[key]);
    106                 ok = 1;
    107                 break;
    108             }
    109             else s.insert(key);
    110         } 
    111         if( !ok ){
    112             printf("%d
    ", i);
    113             for(set<ull>::iterator iter = s.begin(); iter != s.end(); iter++ ){
    114                 mp[*iter] = i;
    115             }
    116         }
    117     }
    118     return 0;
    119 }

    好了,这是加了找重心优化的树的同构(思想很简单,就是让所有的一个或两个重心去跑,然后取最大的,就这样)(20毫秒) 加油,多学多练。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<vector>
      4 #include<map>
      5 #include<algorithm>
      6 #define ull unsigned long long
      7 #define magic 107ull
      8 #define rep(i,j,k) for(int i = j; i <= k; i++)
      9 #define maxn 60
     10 using namespace std;
     11 
     12 int read()
     13 {
     14     int s = 0, t = 1; char c = getchar();
     15     while( !isdigit(c) ){
     16         if( c == '-' ) t = -1; c = getchar();
     17     }
     18     while( isdigit(c) ){
     19         s = s * 10 + c -'0'; c = getchar();
     20     }
     21     return s * t;
     22 }
     23 
     24 ull pow(ull key,int n)
     25 {
     26     ull ret = 1ull;
     27     while( n ){
     28        if( n & 1 ){
     29              ret *= key;
     30        }
     31        key *= key, n >>= 1;
     32     }
     33     return ret;
     34 }
     35 
     36 struct hash{
     37 int length; ull key;
     38 
     39 hash(): length(0), key(0) {}
     40 hash(char c): length(1), key(c) {}
     41 hash(int l,ull key): length(l), key(key) {}
     42 };
     43 vector<hash> childs[maxn];
     44 
     45 bool operator < (const hash&a, const hash&b){
     46     return a.key < b.key;
     47 }
     48 
     49 hash operator + (const hash&a, const hash& b){
     50     return hash(a.length+b.length,a.key*pow(magic,b.length)+b.key);
     51 }
     52 
     53 void operator += (hash&a,const hash&b){
     54     a = a + b;
     55 }
     56 
     57 vector<int> g[maxn];
     58 
     59 hash dfs(int pre,int now)
     60 {
     61     hash ret;
     62     childs[now].clear(); int s = g[now].size();
     63     rep(i,0,s-1){
     64         int to = g[now][i];
     65         if( to == pre ) continue;
     66         childs[now].push_back(dfs(now,to));
     67     }
     68     sort(childs[now].begin(),childs[now].end());
     69     for(vector<hash>::iterator iter = childs[now].begin(); iter != childs[now].end(); iter++){
     70         ret += *iter;
     71     }
     72     ret = '(' +  ret + ')';
     73     return ret;
     74     
     75 }
     76 
     77 ull gethash(int root)
     78 {
     79     return dfs(-1,root).key;
     80 }
     81 
     82 map<ull,int> mp; 
     83 
     84 void clear()
     85 {
     86     rep(i,1,maxn) g[i].clear();
     87 }
     88 
     89 int son[maxn], f[maxn], m,  mx;
     90 void find_root(int pre,int now)
     91 {
     92     son[now] = 1, f[now] = 0; int s = g[now].size();
     93     rep(i,0,s-1){
     94         int to = g[now][i];
     95         if( to != pre ){
     96             find_root(now,to);
     97             son[now] += son[to];
     98             if( son[to] > f[now] ) f[now] = son[to];
     99         }
    100     }
    101     if( m - son[now] > f[now] ) f[now] = m - son[now];
    102     if( f[now] < mx ) mx = f[now];
    103 }
    104 
    105 int main()
    106 {
    107     int n = read();
    108     rep(i,1,n){
    109         clear(); 
    110         m = read(); mx = 0x7ffffff;
    111         rep(j,1,m){
    112             int x = read();
    113             if( x ) g[j].push_back(x), g[x].push_back(j);
    114         }
    115         find_root(0,1); ull key = 0;
    116         rep(j,1,m){
    117             if( f[j] == mx ) {
    118                 ull value = gethash(j);
    119                 if( value > key ) key = value;
    120             }
    121         }
    122         if( mp[key] ) printf("%d
    ", mp[key]);
    123         else {
    124             printf("%d
    ", i);
    125             mp[key] = i;
    126         }
    127     }
    128     return 0;
    129 }
  • 相关阅读:
    时间戳 时间 相互转换
    CS Academy Remove Update
    一周水题集锦 2017 9.4
    计蒜客 16877 卡牌游戏
    计蒜客 16876 韩梅梅的抽象画
    九度OJ 题目1534:数组中第K小的数字
    CS Academy Switch the Lights
    CF AIM Tech Round 4 C. Sorting by Subsequences
    CF Round 430 C. Ilya And The Tree
    CS Academy Round 44 Check DFS
  • 原文地址:https://www.cnblogs.com/83131yyl/p/5102063.html
Copyright © 2011-2022 走看看