[海军国际项目办公室]数树

2024-03-16 22:38

本文主要是介绍[海军国际项目办公室]数树,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

数树

题目概述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

题解

我们先不考虑树 T 2 T2 T2树内部的同构情况,算出总的方案数,最后除去同构的方案。
显然,树 T 1 T1 T1 T 2 T2 T2都是无根树,我们不妨先给 T 1 T1 T1定一个根,这样的话, T 1 T1 T1中每一种能映射到 T 2 T2 T2上的合法方案都会存在一个确定的根,在我们将我们把 T 2 T2 T2的根定义为该对应点时,这两块刚好能够匹配。
我们不妨枚举在 T 2 T2 T2中每个点为根时的情况,这样所有点的相对高度与位置都是确定的,我们可以把它放到 T 1 T1 T1上,看有多少个连通块能跟其匹配。

T 2 T2 T2放到 T 1 T1 T1求出匹配显然可以用 d p dp dp来求出。
我们定义 d p i , j dp_{i,j} dpi,j表示 T 1 T1 T1上的点 i i i匹配 T 2 T2 T2上的点 j j j的方案数。
其转移过程我们可以通过状压来维护。
由于我们此时 T 2 T2 T2的根是固定的,所以点 j j j T 2 T2 T2上的儿子也是固定的。
我们要让 i i i T 1 T1 T1上的儿子依次匹配 j j j T 2 T2 T2上的儿子,求出匹配的方案数。
我们定义 f i , j , S f_{i,j,S} fi,j,S表示 i i i T 1 T1 T1上的儿子匹配了 j j j T 2 T2 T2上的儿子集合为 S S S的方案数,其转移显然是一个背包的过程,加入的 i i i的儿子,枚举其匹配 j j j的哪一个儿子或者不匹配。
显然, d p i , j = f i , j , s o n j dp_{i,j}=f_{i,j,son_{j}} dpi,j=fi,j,sonj,其中 s o n j son_{j} sonj表示 j j j儿子的全集。
∑ i = 1 n d p i , r t \sum_{i=1}^{n}dp_{i,rt} i=1ndpi,rt就是 T 2 T2 T2 r t rt rt为根放到 T 1 T1 T1上匹配得到的方案数之和。
我们要枚举 r t rt rt,整个 d p dp dp的过程是 O ( n m 2 2 m ) O\left(nm^22^m\right) O(nm22m)的。

但是 T 2 T2 T2的内部存在同构的情况,比如一棵完全二叉树,交换它的左右儿子,树的形态并没有发生改变,但如果是我们上面的匹配过程的话,它是会被重复计算的。
即相同的点集,存在不同的映射方法,而这种映射方法会导致我们的重复计算。
而这种映射方法在匹配的根不同的情况下依旧可能导致相同,如果只根据匹配方的点集是相当麻烦的。
我们不如考虑以某一个点为根的树形态会产生多少的同构,也就是按以这个节点为根的树与我们的原 T 2 T2 T2进行上面 d p dp dp转移的匹配,得到的 h r t h_{rt} hrt表示以 r t rt rt为根的 T 2 T2 T2与原 T 2 T2 T2的同构数。
将原来的 ∑ i = 1 n d p i , r t \sum_{i=1}^{n}dp_{i,rt} i=1ndpi,rt除去 h r t h_{rt} hrt即可,因为原来匹配的就是以 r t rt rt为根的树,它产生的同构树与 h r t h_{rt} hrt相当。
所以这样跑两趟 d p dp dp就可以了。

时间复杂度 O ( ( n + m ) m 2 2 m ) O\left((n+m)m^22^m\right) O((n+m)m22m)

源码

#include<bits/stdc++.h>
using namespace std;
#define MAXN 3005
#define MAXM (1<<10)+5
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define debug(x) cerr<<#x<<"="<<x<<'\n'
typedef long long LL;
typedef unsigned long long uLL;     
const LL INF=0x3f3f3f3f3f3f3f3f;  
const int mo=998244353;
const int inv2=499122177;
const int jzm=2333;
const int n1=50;
const int zero=10000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<LL,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){_T f=1;x=0;char s=getchar();while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}x*=f;
}
template<typename _T>
void print(_T x){putchar('\n');while(x>9){putchar((x%10)|'0');x/=10;}putchar(x|'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
int n,m,dp[MAXN][12],f[MAXM],tmp[MAXM],g[12][12],ans,ord[15],h[12],sumtr;
vector<int>A[MAXN],B[15],G[15];
void dosaka1(int u,int fa){G[u].clear();int siz=B[u].size();for(int i=0;i<siz;i++){int v=B[u][i];if(v==fa)continue;dosaka1(v,u);G[u].pb(v);}
}
void dosaka2(int u,int fa){int siz=A[u].size();for(int i=0;i<siz;i++)if(A[u][i]!=fa)dosaka2(A[u][i],u);for(int i=1;i<=m;i++){f[0]=1;int sz=G[i].size();for(int j=0;j<sz;j++)ord[j]=G[i][j];if(sz)for(int j=0;j<siz;j++){int v=A[u][j];if(v==fa)continue;for(int S=0;S<(1<<sz);S++)tmp[S]=f[S];for(int k=0;k<sz;k++)for(int S=0;S<(1<<sz);S++)if(!(S&(1<<k)))Add(tmp[S|(1<<k)],1ll*dp[v][ord[k]]*f[S]%mo,mo);for(int S=0;S<(1<<sz);S++)f[S]=tmp[S],tmp[S]=0;}dp[u][i]=f[(1<<sz)-1];for(int S=0;S<(1<<sz);S++)f[S]=0;}
}
void dosaka3(int u,int fa){int siz=B[u].size();for(int i=0;i<siz;i++)if(B[u][i]!=fa)dosaka3(B[u][i],u);for(int i=1;i<=m;i++){f[0]=1;int sz=G[i].size();for(int j=0;j<sz;j++)ord[j]=G[i][j];if(sz)for(int j=0;j<siz;j++){int v=B[u][j];if(v==fa)continue;for(int S=0;S<(1<<sz);S++)tmp[S]=f[S];for(int k=0;k<sz;k++)for(int S=0;S<(1<<sz);S++)if(!(S&(1<<k)))Add(tmp[S|(1<<k)],1ll*g[v][ord[k]]*f[S]%mo,mo);for(int S=0;S<(1<<sz);S++)f[S]=tmp[S],tmp[S]=0;}g[u][i]=f[(1<<sz)-1];for(int S=0;S<(1<<sz);S++)f[S]=0;}
}
signed main(){freopen("count.in","r",stdin);freopen("count.out","w",stdout);read(n);for(int i=1;i<n;i++){int u,v;read(u);read(v);A[u].pb(v);A[v].pb(u);}read(m);for(int i=1;i<m;i++){int u,v;read(u);read(v);B[u].pb(v);B[v].pb(u);}for(int rt=1;rt<=m;rt++){dosaka1(rt,0);for(int j=1;j<=m;j++)dosaka3(j,0),Add(h[j],g[j][rt],mo);	}for(int rt=1;rt<=m;rt++){dosaka1(rt,0);dosaka2(1,0);int summ=0;for(int i=1;i<=n;i++)Add(summ,dp[i][rt],mo);Add(ans,1ll*summ%mo*qkpow(h[rt],mo-2,mo)%mo,mo);}printf("%d\n",ans);return 0;
}

谢谢!!!

这篇关于[海军国际项目办公室]数树的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/816951

相关文章

部署Vue项目到服务器后404错误的原因及解决方案

《部署Vue项目到服务器后404错误的原因及解决方案》文章介绍了Vue项目部署步骤以及404错误的解决方案,部署步骤包括构建项目、上传文件、配置Web服务器、重启Nginx和访问域名,404错误通常是... 目录一、vue项目部署步骤二、404错误原因及解决方案错误场景原因分析解决方案一、Vue项目部署步骤

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

配置springboot项目动静分离打包分离lib方式

《配置springboot项目动静分离打包分离lib方式》本文介绍了如何将SpringBoot工程中的静态资源和配置文件分离出来,以减少jar包大小,方便修改配置文件,通过在jar包同级目录创建co... 目录前言1、分离配置文件原理2、pom文件配置3、使用package命令打包4、总结前言默认情况下,

python实现简易SSL的项目实践

《python实现简易SSL的项目实践》本文主要介绍了python实现简易SSL的项目实践,包括CA.py、server.py和client.py三个模块,文中通过示例代码介绍的非常详细,对大家的学习... 目录运行环境运行前准备程序实现与流程说明运行截图代码CA.pyclient.pyserver.py参

IDEA运行spring项目时,控制台未出现的解决方案

《IDEA运行spring项目时,控制台未出现的解决方案》文章总结了在使用IDEA运行代码时,控制台未出现的问题和解决方案,问题可能是由于点击图标或重启IDEA后控制台仍未显示,解决方案提供了解决方法... 目录问题分析解决方案总结问题js使用IDEA,点击运行按钮,运行结束,但控制台未出现http://

解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题

《解决IDEA使用springBoot创建项目,lombok标注实体类后编译无报错,但是运行时报错问题》文章详细描述了在使用lombok的@Data注解标注实体类时遇到编译无误但运行时报错的问题,分析... 目录问题分析问题解决方案步骤一步骤二步骤三总结问题使用lombok注解@Data标注实体类,编译时

C语言小项目实战之通讯录功能

《C语言小项目实战之通讯录功能》:本文主要介绍如何设计和实现一个简单的通讯录管理系统,包括联系人信息的存储、增加、删除、查找、修改和排序等功能,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录功能介绍:添加联系人模块显示联系人模块删除联系人模块查找联系人模块修改联系人模块排序联系人模块源代码如下

SpringBoot项目中Maven剔除无用Jar引用的最佳实践

《SpringBoot项目中Maven剔除无用Jar引用的最佳实践》在SpringBoot项目开发中,Maven是最常用的构建工具之一,通过Maven,我们可以轻松地管理项目所需的依赖,而,... 目录1、引言2、Maven 依赖管理的基础概念2.1 什么是 Maven 依赖2.2 Maven 的依赖传递机

Vue项目中Element UI组件未注册的问题原因及解决方法

《Vue项目中ElementUI组件未注册的问题原因及解决方法》在Vue项目中使用ElementUI组件库时,开发者可能会遇到一些常见问题,例如组件未正确注册导致的警告或错误,本文将详细探讨这些问题... 目录引言一、问题背景1.1 错误信息分析1.2 问题原因二、解决方法2.1 全局引入 Element

Python 中 requests 与 aiohttp 在实际项目中的选择策略详解

《Python中requests与aiohttp在实际项目中的选择策略详解》本文主要介绍了Python爬虫开发中常用的两个库requests和aiohttp的使用方法及其区别,通过实际项目案... 目录一、requests 库二、aiohttp 库三、requests 和 aiohttp 的比较四、requ