『Andrew and Chemistry 树同构』

(4) 2024-04-30 18:17

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说『Andrew and Chemistry 树同构』,希望能够帮助你!!!。


Andrew and Chemistry

Description

During the chemistry lesson Andrew learned that the saturated hydrocarbons (alkanes) enter into radical chlorination reaction. Andrew is a very curious boy, so he wondered how many different products of the reaction may be forms for a given alkane. He managed to solve the task for small molecules, but for large ones he faced some difficulties and asks you to help.

Formally, you are given a tree consisting of nn vertices, such that the degree of each vertex doesn't exceed 44 . You have to count the number of distinct non-isomorphic trees that can be obtained by adding to this tree one new vertex and one new edge, such that the graph is still the tree and the degree of each vertex doesn't exceed 44 .

Two trees are isomorphic if there exists a bijection f(v)f(v) such that vertices uu and vv are connected by an edge if and only if vertices f(v)f(v) and f(u)f(u) are connected by an edge.

Input Format

The first line of the input contains an integer nn ( 1<=n<=1000001<=n<=100000 ) — the number of vertices in the tree.

Then follow n-1n−1 lines with edges descriptions. Each edge is given by two integers u_{i}ui​ and v_{i}vi​ ( 1<=u_{i},v_{i}<=n1<=ui​,vi​<=n ) — indices of vertices connected by an edge. It's guaranteed that the given graph is a tree and the degree of each vertex doesn't exceed 44 .

Output Format

Print one integer — the answer to the question.

Sample Input

4
1 2
2 3
2 4

Sample Output

2

解析

题目大意:给你一个有\(n\)个点的树。当每一个点的度不超过\(4\)时这棵树是合法的。现在让你再添加一个点,在树仍然合法的情况下,一共有多少种树。当两棵树同构时视作同一种。

思路就是枚举,枚举每一个原来度数小于\(4\)的点作为加点的点,然后只要看以该点为根时这棵树是否与之前的方案同构即可。

同构就是用树哈希判,这里的方法类似于记忆化搜索:设\(f[x][fa]\)代表以\(fa\)\(x\)的父亲时,子树\(x\)\(hash\)值。当这个状态没有\(hash\)值的时候,我们就取其子节点的所有\(hash\)值放在一个集合里做一次映射,得到一个正整数权值,当做\(hash\)值即可。

显然这样可以保证正确性:叶节点构造的集合都是空集,其映射的正整数也是相同的,当两棵树同构的时候,对应节点也都会因为相同的集合映射出相同的\(hash\)值,那这样树的权值也就是相同的。

而记忆化搜索就帮助我们保证了效率,当然,开不下的数组可以用\(map\),因为我们知道状态总数是不超空间的:一条边只对应了一个状态。

\(Code:\)

#include <bits/stdc++.h> using namespace std; const int N = 100020; int n , cnt; vector < int > e[N]; map < int , int > f[N]; map < vector<int> , int > List; set < int > S; inline int dp(int x,int fa) { if ( f[x].count(fa) ) return f[x][fa]; vector < int > temp; for ( int i = 0; i < e[x].size(); i++ ) { int y = e[x][i]; if ( y == fa ) continue; temp.push_back( dp( y , x ) ); } sort( temp.begin() , temp.end() ); if ( !List.count( temp ) ) List[ temp ] = ++cnt; return f[x][fa] = List[ temp ]; } int main(void) { scanf("%d",&n); for ( int i = 1; i < n; i++ ) { int u , v; scanf("%d%d",&u,&v); e[u].push_back( v ); e[v].push_back( u ); } for ( int i = 1; i <= n; i++ ) if ( e[i].size() < 4 ) S.insert( dp( i , 0 ) ); printf("%d\n",S.size()); return 0; } 

转载于:https://www.cnblogs.com/Parsnip/p/11203868.html

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复