Hourrank 21 Tree Isomorphism 树hash

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

题目大意:

给出一棵树, 求有多少本质不同的子树。   N <= 19

 

下面给出我综合了网上一些做法后设计的hash函数(我不会证明碰撞概率)

判断两棵有根树是否相同:

将子树的Hash值从小到大排序, Hash(x) =  A * p xor Hash(son_1) mod q  * p  xor Hash(son_2) mod q ....  * p xor Hash(son_k) mod q * B mod q 

 

判断两棵无根树是否相同:

找到重心 u, v(u 可能等于v, 即只有一个重心)  分别以它们为根求有根树Hash。不妨设 Hash(u) <= Hash(v)

Unrooted_Hash(x) = triple(n, u, v)  n为节点数。

 

对于本题, 只要暴力将每个子树的Unrooted_Hash 插入到set里就好了。

 

代码:

  1 //https://www.hackerrank.com/contests/hourrank-21/challenges/tree-isomorphism
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <cmath>
  6 #include <algorithm>
  7 #include <vector>
  8 #include <map>
  9 #include <queue>
 10 #include <set>
 11 using namespace std;
 12  
 13 typedef long long ll;
 14  
 15 #define N 20
 16 const int INF = 1 << 30;
 17 const int P = 10007, A = 31, B = 7;
 18 const ll mod = 1e12 + 22333;
 19 const double pi = acos(-1);
 20 
 21 
 22 vector<int> E[N], cone;
 23 int size[N], cnt;
 24 set<pair<int, pair<ll, ll> > > st;
 25 
 26 int DFS_SIZE(int x, int pre)
 27 {
 28     int res = 1;
 29     for (int i = 0; i < E[x].size(); ++i)
 30     {
 31         int y = E[x][i];
 32         if (y == pre) continue;
 33         res += DFS_SIZE(y, x);
 34     }
 35     return size[x] = res;
 36 }
 37 
 38 void Find_Cone(int x, int pre)
 39 {
 40     bool f = true;
 41     for (int i = 0; i < E[x].size(); ++i)
 42     {
 43         int y = E[x][i];
 44         if (y == pre) continue;
 45         Find_Cone(y, x);
 46         if (size[y] > cnt / 2) f = false;
 47     }
 48     if (cnt - size[x] > cnt / 2) f = false;
 49     if (f) cone.push_back(x);
 50 }
 51 
 52 ll Hash(int x, int pre)
 53 {
 54     vector<ll> res;
 55     for (int i = 0; i < E[x].size(); ++i)
 56     {
 57         int y = E[x][i];
 58         if (y == pre) continue;
 59         res.push_back(Hash(y, x));
 60     }
 61     sort(res.begin(), res.end());
 62     
 63     ll h = A;
 64     for (int i = 0; i < res.size(); ++i) h = (h * P ^ res[i]) % mod; 
 65     h = h * B % mod;
 66     return h;
 67 }
 68 
 69 int main()
 70 {
 71     //freopen("in.in", "r", stdin);
 72     //freopen("out.out", "w", stdout);
 73      
 74      int n, x, y, a[20], b[20];
 75      cin >> n;
 76      for (int i = 0; i < n - 1; ++i) cin >> a[i] >> b[i], --a[i], --b[i];
 77      for (int mask = 1; mask < (1 << n); ++mask)
 78      {
 79          for (int i = 0; i < n; ++i) E[i].clear(); 
 80          cone.clear(); cnt = 0;
 81          for (int i = 0; i < n - 1; ++i)
 82          {
 83              if ((mask & (1 << a[i])) && (mask & (1 << b[i])))
 84             {
 85                 E[a[i]].push_back(b[i]);
 86                 E[b[i]].push_back(a[i]);
 87             }    
 88         }
 89         int root;
 90         for (int i = 0; i < n; ++i) if (mask & (1 << i)) root = i, ++cnt;
 91         if (DFS_SIZE(root, -1) != cnt) continue;
 92         
 93         Find_Cone(root, -1);
 94         if (cone.size() == 1)
 95         {
 96             ll h = Hash(cone[0], -1);
 97             st.insert(make_pair(cnt, make_pair(h, h)));
 98         }
 99         else
100         {
101             ll h1 = Hash(cone[0], -1), h2 = Hash(cone[1], -1);
102             if (h1 > h2) swap(h1, h2);
103             st.insert(make_pair(cnt, make_pair(h1, h2)));
104         }
105     }
106     printf("%d\n", (int)st.size());
107     return 0;
108 } 
View Code

 

转载于:https://www.cnblogs.com/vb4896/p/6972197.html

### Graph Isomorphism Network (GIN): 原理、实现与应用 #### GIN 的基本概念 Graph Isomorphism Network (GIN) 是一种用于图结构数据处理的强大神经网络模型。它通过设计特定的消息传递机制来捕获节点之间的关系,从而能够区分不同类型的图结构[^1]。 #### 工作原理 GIN 的核心在于消息传递机制的设计以及如何利用聚合函数来更新节点特征。具体来说,GIN 使用了一种形式化的表达方式 \( h_v^{(k+1)} = \text{MLP}(h_v^{(k)} + \text{AGG}(\{h_u^{(k)}, u\in N(v)\}))\) 来描述节点状态的更新过程。其中: - \( h_v^{(k)} \) 表示第 k 层中节点 v 的隐藏状态; - \( N(v) \) 表示节点 v 的邻居集合; - AGG 表示某种聚合操作(通常为求和或平均); - MLP 表示多层感知器。 这种设计使得 GIN 能够逼近 Weisfeiler-Lehman 图同构测试的能力,因此具有较强的表征能力。 #### 实现细节 在实际实现过程中,可以借助流行的深度学习框架完成 GIN 的构建。以下是基于 Python 和 JAX 库的一个简单代码示例: ```python import jax.numpy as jnp from flax import linen as nn class GINLayer(nn.Module): mlp: nn.Module @nn.compact def __call__(self, node_features, adjacency_matrix): aggregated_messages = jnp.dot(adjacency_matrix, node_features) updated_node_features = self.mlp(node_features + aggregated_messages) return updated_node_features class GINModel(nn.Module): num_layers: int hidden_dim: int output_dim: int @nn.compact def __call__(self, node_features, adjacency_matrix): for _ in range(self.num_layers - 1): mlp_layer = nn.Sequential([nn.Dense(self.hidden_dim), nn.ReLU()]) gin_layer = GINLayer(mlp=mlp_layer) node_features = gin_layer(node_features, adjacency_matrix) final_mlp = nn.Sequential([ nn.Dense(self.output_dim), nn.LogSoftmax() ]) return final_mlp(node_features) # Example usage of the model node_features = jnp.array([[0., 1.], [1., 0.]]) # Example features adjacency_matrix = jnp.array([[0., 1.], [1., 0.]]) # Example graph structure model = GINModel(num_layers=2, hidden_dim=8, output_dim=3) params = model.init(jax.random.PRNGKey(0), node_features, adjacency_matrix) output = model.apply(params, node_features, adjacency_matrix) print(output) ``` 上述代码展示了如何定义一个简单的 GIN 模型并对其进行初始化和前向传播计算。 #### 应用领域 GIN 广泛应用于多个机器学习场景,特别是在涉及复杂图结构的任务上表现优异。常见的应用场景包括但不限于分子性质预测、社交网络分析和社会科学中的群体行为建模等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值