目录:
题目:
分析:
小编认为使用动态规划做这题,使非常方便且好理解的,所以,此文就着重介绍下dp做法:
f[i][j]
f
[
i
]
[
j
]
代表一树一中的i与树二的j为根节点的子树的最大同构
而对于具体做法,小编还想各位结合代码进行理解:
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define LL long long
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define maxn 1005
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
int ea[1001][10],eb[1001][10],f[1001][1001],x,y,n,m;
bool tf[1001];
void dfs1(int k,int s)
{
if(k>ea[x][0]) {if(f[x][y]<s) f[x][y]=s;return;}
//当点x的孩子访问完时,是时候返回值了
dfs1(k+1,s);
bool pd=0;
for(int j=1;j<=eb[y][0];j++)
if(tf[j]==0)//避免重复
{
tf[j]=1;
dfs1(k+1,s+f[ea[x][k]][eb[y][j]]);
//加上子节点的最大同构值
tf[j]=0;
}
if(f[x][y]<s) f[x][y]=s;
}
void dfs(int k)
{
if(ea[k][0]==0)//当k节点没有孩子时
{
for(int i=1;i<=m;i++)
f[k][i]=1;//只有k节点一个可以同构
return;
}
for(int i=1;i<=ea[k][0];i++)
dfs(ea[k][i]);//dfs每个孩子
for(int i=1;i<=m;i++)
{
if(eb[i][0]==0) f[k][i]=1;//当i节点没有孩子时(同上)
else
{
x=k;y=i;//记录
dfs1(1,0);//开始dfs第二棵树
f[k][i]++;//最后算上k节点一个
}
}
}
int main()
{
n=read();m=read();
//ea、eb的0号下标为长度记录
for(int i=1;i<n;i++)
{
x=read();y=read();
ea[x][++ea[x][0]]=y;//建表
}
for(int i=1;i<m;i++)
{
x=read();y=read();
eb[x][++eb[x][0]]=y;
}
dfs(1);//从树一的根节点开始
printf("%d",f[1][1]);
return 0;
}