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\n", mp[key]);
106                 ok = 1;
107                 break;
108             }
109             else s.insert(key);
110         } 
111         if( !ok ){
112             printf("%d\n", 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\n", mp[key]);
123         else {
124             printf("%d\n", i);
125             mp[key] = i;
126         }
127     }
128     return 0;
129 }

 

posted on 2016-01-05 13:39  83131  阅读(236)  评论(0编辑  收藏  举报

导航