#include<bits/stdc++.h>
using namespace std;
#define N 2001
#define M 1<<12
#define MOD 1000000007
int len(int x){return 32-__builtin_clz(x);}
int Union(int x,int y){return (x<<len(y))|y;}
struct Tree
{
    int n;
    int f[M][2];
    vector<int>d[N];
    map<int,int>num[N],ans;
    map<int,vector<int> >mp;
    void read()
      {
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
        d[i].clear();
      for(int i=2;i<=n;i++)
        {
        int u,v;
        scanf("%d%d",&u,&v);
        d[u].push_back(v);
        d[v].push_back(u);
        }
      }
    int dfs(int cur,int pre)
      {
      int res=1;
      vector<int>tmp;
      for(auto nxt:d[cur])if(nxt!=pre)
        tmp.push_back(dfs(nxt,cur));
      sort(tmp.begin(),tmp.end());
      for(auto x:tmp)res=Union(res,x);
      res<<=1;
      if(!mp.count(res))mp[res]=tmp;
      return res;
      }
    void getID()
      {
      for(int i=1;i<=n;i++)
        dfs(i,0);
      }
    void DP(int cur,int pre,const Tree &T)
      {
      for(auto nxt:d[cur])if(nxt!=pre)DP(nxt,cur,T);
      for(const auto &pi:T.mp)
        {
        auto &types=pi.second;
        int id=pi.first,n=types.size(),now=0,lst=1;
        for(int i=0;i<(1<<n);i++)f[i][0]=f[i][1]=0;
        f[0][0]=1;
        for(auto nxt:d[cur])if(nxt!=pre)
          {
          now^=1,lst^=1;
          for(int i=0;i<(1<<n);i++)
            f[i][now]=f[i][lst];
          for(int i=0;i<n;i++)
            if(num[nxt][types[i]])
              for(int j=(1<<n)-1;j>=0;j--)
                if(f[j][lst] && !((1<<i)&j) && !(i && types[i]==types[i-1] && !((1<<(i-1))&j)))
                  (f[(1<<i)|j][now]+=1ll*f[j][lst]*num[nxt][types[i]]%MOD)%=MOD;
          }
        if(f[(1<<n)-1][now])
          {
          num[cur][id]=f[(1<<n)-1][now];
          (ans[id]+=num[cur][id])%=MOD;
          }
        }
      }
}S,T;
set<int>s;
vector<int>d[13];
void fuck(int cur,int pre)
{
	for(int i=1;i<=12;i++)
	  T.d[i]=d[i];
	T.n=cur;
	T.getID();
	if(cur==12)return;
	d[cur].push_back(cur+1);
	fuck(cur+1,cur);
	d[cur].pop_back();
	if(pre!=0)
	  {
	  d[pre].push_back(cur+1);
	  fuck(cur+1,pre);
	  d[pre].pop_back();
	  }
}
int main()
{
	fuck(1,0);
	int t;
    S.read();
    S.DP(1,0,T);
    t=1;
    while(t--)
      {
      T.read();
      int ans=0;
      s.clear();
      for(int i=1;i<=T.n;i++)
        s.insert(T.dfs(i,0));
      for(auto x:s)(ans+=S.ans[x])%=MOD;
      printf("%d\n",ans);
	  }
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define N 1001
#define M 1<<12
#define MOD 1000000007
int len(int x){return 32-__builtin_clz(x);}
int Union(int x,int y){return (x<<len(y))|y;}
struct Tree
{
	int n,ans;
	int f[M][2];
	vector<int>d[N];
	map<int,int>num[N];
	map<int,vector<int> >mp;
	void read()
	  {
	  scanf("%d",&n);
	  for(int i=2;i<=n;i++)
	    {
	    int u,v;
	    scanf("%d%d",&u,&v);
	    d[u].push_back(v);
	    d[v].push_back(u);
		}
	  }
	int dfs(int cur,int pre)
	  {
	  int res=1;
	  vector<int>tmp;
	  for(auto nxt:d[cur])if(nxt!=pre)
	    tmp.push_back(dfs(nxt,cur));
	  sort(tmp.begin(),tmp.end());
	  for(auto x:tmp)res=Union(res,x);
	  res<<=1;
	  if(!mp.count(res))mp[res]=tmp;
	  //cout<<cur<<" "<<pre<<" "<<res<<endl;
	  return res;
	  }
	void getID()
	  {
	  for(int i=1;i<=n;i++)
	    dfs(i,0);
	  }
	void DP(int cur,int pre,const Tree &T)
	  {
	  for(auto nxt:d[cur])if(nxt!=pre)DP(nxt,cur,T);
	  for(const auto &pi:T.mp)
	    {
	    auto &types=pi.second;
	    int id=pi.first,n=types.size(),now=0,lst=1;
	    for(int i=0;i<(1<<n);i++)f[i][0]=f[i][1]=0;
	    f[0][0]=1;
	    for(auto nxt:d[cur])if(nxt!=pre)
	      {
	      now^=1,lst^=1;
	      for(int i=0;i<(1<<n);i++)
	        f[i][now]=f[i][lst];
	      for(int i=0;i<n;i++)
	        if(num[nxt][types[i]])
	          for(int j=(1<<n)-1;j>=0;j--)
	            if(f[j][lst] && !((1<<i)&j) && !(i && types[i]==types[i-1] && !((1<<(i-1))&j)))
	              (f[(1<<i)|j][now]+=1ll*f[j][lst]*num[nxt][types[i]]%MOD)%=MOD;
		  }
		if(f[(1<<n)-1][now])
		  {
		  //cout<<id<<endl;
		  num[cur][id]=f[(1<<n)-1][now];
		  if(len(id)==2*T.n)(ans+=num[cur][id])%=MOD;
		  }
		}
	  }
}S,T;
int main()
{
	S.read();
	T.read();
	T.getID();
	S.DP(1,0,T);
	printf("%d\n",S.ans);
}


#include<bits/stdc++.h>
using namespace std;
#define N 1001
#define M 1<<12
#define MOD 1000000007
int len(int x){return 32-__builtin_clz(x);}
int Union(int x,int y){return (x<<len(y))|y;}
struct Tree
{
	int n,ans;
	int f[M][2];
	int num[N][M];
	vector<int>d[N];
	map<int,vector<int> >mp;
	void read()
	  {
	  scanf("%d",&n);
	  for(int i=2;i<=n;i++)
	    {
	    int u,v;
	    scanf("%d%d",&u,&v);
	    d[u].push_back(v);
	    d[v].push_back(u);
		}
	  }
	int dfs(int cur,int pre)
	  {
	  int res=1;
	  vector<int>tmp;
	  for(auto nxt:d[cur])if(nxt!=pre)
	    tmp.push_back(dfs(nxt,cur));
	  sort(tmp.begin(),tmp.end());
	  for(auto x:tmp)res=Union(res,x);
	  res<<=1;
	  if(!mp.count(res))mp[res]=tmp;
	  //cout<<cur<<" "<<pre<<" "<<res<<endl;
	  return res;
	  }
	void getID()
	  {
	  for(int i=1;i<=n;i++)
	    dfs(i,0);
	  }
	void DP(int cur,int pre,const Tree &T)
	  {
	  for(auto nxt:d[cur])if(nxt!=pre)DP(nxt,cur,T);
	  for(const auto &pi:T.mp)
	    {
	    auto &types=pi.second;
	    int id=pi.first,n=types.size(),now=0,lst=1;
	    for(int i=0;i<(1<<n);i++)f[i][0]=f[i][1]=0;
	    f[0][0]=1;
	    for(auto nxt:d[cur])if(nxt!=pre)
	      {
	      now^=1,lst^=1;
	      for(int i=0;i<(1<<n);i++)
	        f[i][now]=f[i][lst];
	      for(int i=0;i<n;i++)
	        if(num[nxt][types[i]])
	          for(int j=(1<<n)-1;j>=0;j--)
	            if(f[j][lst] && !((1<<i)&j) && !(i && types[i]==types[i-1] && !((1<<(i-1))&j)))
	              (f[(1<<i)|j][now]+=1ll*f[j][lst]*num[nxt][types[i]]%MOD)%=MOD;
		  }
		if(f[(1<<n)-1][now])
		  {
		  //cout<<id<<endl;
		  num[cur][id]=f[(1<<n)-1][now];
		  if(len(id)==2*T.n)(ans+=num[cur][id])%=MOD;
		  }
		}
	  }
}S,T;
int main()
{
	S.read();
	T.read();
	T.getID();
	S.DP(1,0,T);
	printf("%d\n",S.ans);
}


#include<bits/stdc++.h>
using namespace std;
#define N 2001
#define M 1<<12
#define MOD 1000000007
int len(int x){return 32-__builtin_clz(x);}
int Union(int x,int y){return (x<<len(y))|y;}
struct Tree
{
    int n;
    int f[M][2];
    vector<int>d[N];
    map<int,int>num[N],ans;
    map<int,vector<int> >mp;
    void read()
      {
      mp.clear();
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
        d[i].clear();
      for(int i=2;i<=n;i++)
        {
        int u,v;
        scanf("%d%d",&u,&v);
        d[u].push_back(v);
        d[v].push_back(u);
        }
      }
    int dfs(int cur,int pre)
      {
      int res=1;
      vector<int>tmp;
      for(auto nxt:d[cur])if(nxt!=pre)
        tmp.push_back(dfs(nxt,cur));
      sort(tmp.begin(),tmp.end());
      for(auto x:tmp)res=Union(res,x);
      res<<=1;
      if(!mp.count(res))mp[res]=tmp;
      return res;
      }
    void getID()
      {
      for(int i=1;i<=n;i++)
        dfs(i,0);
      }
    void DP(int cur,int pre,const Tree &T)
      {
      for(auto nxt:d[cur])if(nxt!=pre)DP(nxt,cur,T);
      for(const auto &pi:T.mp)
        {
        auto &types=pi.second;
        int id=pi.first,n=types.size(),now=0,lst=1;
        for(int i=0;i<(1<<n);i++)f[i][0]=f[i][1]=0;
        f[0][0]=1;
        for(auto nxt:d[cur])if(nxt!=pre)
          {
          now^=1,lst^=1;
          for(int i=0;i<(1<<n);i++)
            f[i][now]=f[i][lst];
          for(int i=0;i<n;i++)
            if(num[nxt][types[i]])
              for(int j=(1<<n)-1;j>=0;j--)
                if(f[j][lst] && !((1<<i)&j) && !(i && types[i]==types[i-1] && !((1<<(i-1))&j)))
                  (f[(1<<i)|j][now]+=1ll*f[j][lst]*num[nxt][types[i]]%MOD)%=MOD;
          }
        if(f[(1<<n)-1][now])
          {
          num[cur][id]=f[(1<<n)-1][now];
          (ans[id]+=num[cur][id])%=MOD;
          }
        }
      }
}S,T;
set<int>s;
int fa[13];
vector<int>d[13];
void fuck(int cur,int pre)
{
	fa[cur]=pre;
	for(int i=1;i<=12;i++)
	  T.d[i]=d[i];
	T.n=cur;
	T.getID();
	if(cur==12)return;
	d[cur].push_back(cur+1);
	fuck(cur+1,cur);
	d[cur].pop_back();
	int x=pre;
	while(x!=0)
	  {
	  d[x].push_back(cur+1);
	  fuck(cur+1,x);
	  d[x].pop_back();
	  x=fa[x];
	  }
}
int main()
{
	fuck(1,0);
	int t;
    S.read();
    S.DP(1,0,T);
    t=1;
    while(t--)
      {
      T.read();
      int ans=0;
      s.clear();
      for(int i=1;i<=T.n;i++)
        s.insert(T.dfs(i,0));
      for(auto x:s)(ans+=S.ans[x])%=MOD;
      printf("%d\n",ans);
	  }
}


#include<bits/stdc++.h>
using namespace std;
#define N 2001
#define M 1<<12
#define NN 16773121
#define MOD 1000000007
int len(int x){return 32-__builtin_clz(x);}
int Union(int x,int y){return (x<<len(y))|y;}
struct Tree
{
    int n,ans[NN];
    int f[M][2];
    vector<int>d[N];
    unordered_map<int,int>num[N];
    unordered_map<int,vector<int> >mp;
    void read()
      {
      mp.clear();
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
        d[i].clear();
      for(int i=2;i<=n;i++)
        {
        int u,v;
        scanf("%d%d",&u,&v);
        d[u].push_back(v);
        d[v].push_back(u);
        }
      }
    int dfs(int cur,int pre)
      {
      int res=1;
      vector<int>tmp;
      for(auto nxt:d[cur])if(nxt!=pre)
        tmp.push_back(dfs(nxt,cur));
      sort(tmp.begin(),tmp.end());
      for(auto x:tmp)res=Union(res,x);
      res<<=1;
      if(!mp.count(res))mp[res]=tmp;
      return res;
      }
    void getID()
      {
      for(int i=1;i<=n;i++)
        dfs(i,0);
      }
    void DP(int cur,int pre,const Tree &T)
      {
      for(auto nxt:d[cur])if(nxt!=pre)DP(nxt,cur,T);
      for(const auto &pi:T.mp)
        {
        auto &types=pi.second;
        int id=pi.first,n=types.size(),now=0,lst=1;
        for(int i=0;i<(1<<n);i++)f[i][0]=f[i][1]=0;
        f[0][0]=1;
        for(auto nxt:d[cur])if(nxt!=pre)
          {
          now^=1,lst^=1;
          for(int i=0;i<(1<<n);i++)
            f[i][now]=f[i][lst];
          for(int i=0;i<n;i++)
            if(num[nxt][types[i]])
              for(int j=(1<<n)-1;j>=0;j--)
                if(f[j][lst] && !((1<<i)&j) && !(i && types[i]==types[i-1] && !((1<<(i-1))&j)))
                  (f[(1<<i)|j][now]+=1ll*f[j][lst]*num[nxt][types[i]]%MOD)%=MOD;
          }
        if(f[(1<<n)-1][now])
          {
          num[cur][id]=f[(1<<n)-1][now];
          (ans[id]+=num[cur][id])%=MOD;
          }
        }
      }
}S,T;
int cnt;
set<int>s;
int fa[13];
vector<int>d[13];
void fuck(int cur,int pre)
{
	fa[cur]=pre;
	for(int i=1;i<=12;i++)
	  T.d[i]=d[i];
	T.n=cur;
	if(cur==12){T.dfs(1,0);return;}
	int x=cur;
	while(x!=0)
	  {
	  d[x].push_back(cur+1);
	  fuck(cur+1,x);
	  d[x].pop_back();
	  x=fa[x];
	  }
}
int main()
{
	fuck(1,0);
	int t;
    S.read();//return 0;
    S.DP(1,0,T);
    t=1;
    //scanf("%d",&t);
    while(t--)
      {
      T.read();
      int ans=0;
      s.clear();
      for(int i=1;i<=T.n;i++)
        s.insert(T.dfs(i,0));
      for(auto x:s)(ans+=S.ans[x])%=MOD;
      printf("%d\n",ans);
	  }
}


#include<bits/stdc++.h>
using namespace std;
#define N 2001
#define M 1<<12
#define NN 16773121
#define MOD 1000000007
int len(int x){return 32-__builtin_clz(x);}
int Union(int x,int y){return (x<<len(y))|y;}
int cnt;
int num_to_id[NN];
int id_to_num[7501];
struct Tree
{
    int n,ans[NN];
    int f[M][2];
    vector<int>d[N];
    int num[N][7501];
    map<int,vector<int> >mp;
    void read()
      {
      mp.clear();
      scanf("%d",&n);
      for(int i=1;i<=n;i++)
        d[i].clear();
      for(int i=2;i<=n;i++)
        {
        int u,v;
        scanf("%d%d",&u,&v);
        d[u].push_back(v);
        d[v].push_back(u);
        }
      }
    int dfs(int cur,int pre)
      {
      int res=1;
      vector<int>tmp;
      for(auto nxt:d[cur])if(nxt!=pre)
        tmp.push_back(dfs(nxt,cur));
      sort(tmp.begin(),tmp.end());
      for(auto x:tmp)res=Union(res,x);
      res<<=1;
      if(!mp.count(res))cnt++,mp[res]=tmp,num_to_id[res]=cnt;
      return res;
      }
    void getID()
      {
      for(int i=1;i<=n;i++)
        dfs(i,0);
      }
    void DP(int cur,int pre,const Tree &T)
      {
      for(auto nxt:d[cur])if(nxt!=pre)DP(nxt,cur,T);
      for(const auto &pi:T.mp)
        {
        auto &types=pi.second;
        int id=pi.first,n=types.size(),now=0,lst=1;
        for(int i=0;i<(1<<n);i++)f[i][0]=f[i][1]=0;
        f[0][0]=1;
        for(auto nxt:d[cur])if(nxt!=pre)
          {
          now^=1,lst^=1;
          for(int i=0;i<(1<<n);i++)
            f[i][now]=f[i][lst];
          for(int i=0;i<n;i++)
            if(num[nxt][num_to_id[types[i]]])
              for(int j=(1<<n)-1;j>=0;j--)
                if(f[j][lst] && !((1<<i)&j) && !(i && types[i]==types[i-1] && !((1<<(i-1))&j)))
                  (f[(1<<i)|j][now]+=1ll*f[j][lst]*num[nxt][num_to_id[types[i]]]%MOD)%=MOD;
          }
        if(f[(1<<n)-1][now])
          {
          num[cur][num_to_id[id]]=f[(1<<n)-1][now];
          (ans[id]+=num[cur][num_to_id[id]])%=MOD;
          }
        }
      }
}S,T;
set<int>s;
int fa[13];
vector<int>d[13];
void fuck(int cur,int pre)
{
	fa[cur]=pre;
	for(int i=1;i<=12;i++)
	  T.d[i]=d[i];
	T.n=cur;
	if(cur==12){T.dfs(1,0);return;}
	int x=cur;
	while(x!=0)
	  {
	  d[x].push_back(cur+1);
	  fuck(cur+1,x);
	  d[x].pop_back();
	  x=fa[x];
	  }
}
int main()
{
	freopen("tree.in","r",stdin);
	fuck(1,0);
	int t;
    S.read();//return 0;
    S.DP(1,0,T);
    t=1;
    //scanf("%d",&t);
    while(t--)
      {
      T.read();
      int ans=0;
      s.clear();
      for(int i=1;i<=T.n;i++)
        s.insert(T.dfs(i,0));
      for(auto x:s)(ans+=S.ans[x])%=MOD;
      printf("%d\n",ans);
	  }
}


#include<bits/stdc++.h>
using namespace std;
#define N 1001
#define M 1<<12
#define MOD 1000000007
int len(int x){return 32-__builtin_clz(x);}
int Union(int x,int y){return (x<<len(y))|y;}
struct Tree
{
	int n,ans;
	int f[M][2];
	vector<int>d[N];
	map<int,int>num[N];
	map<int,vector<int> >mp;
	void read()
	  {
	  scanf("%d",&n);
	  for(int i=2;i<=n;i++)
	    {
	    int u,v;
	    scanf("%d%d",&u,&v);
	    if(n==1000 && 2<=i && i<=20)
	      printf("%d %d\n",u,v);
	    d[u].push_back(v);
	    d[v].push_back(u);
		}
	  }
	int dfs(int cur,int pre)
	  {
	  int res=1;
	  vector<int>tmp;
	  for(auto nxt:d[cur])if(nxt!=pre)
	    tmp.push_back(dfs(nxt,cur));
	  sort(tmp.begin(),tmp.end());
	  for(auto x:tmp)res=Union(res,x);
	  res<<=1;
	  if(!mp.count(res))mp[res]=tmp;
	  //cout<<cur<<" "<<pre<<" "<<res<<endl;
	  return res;
	  }
	void getID()
	  {
	  for(int i=1;i<=n;i++)
	    dfs(i,0);
	  }
	void DP(int cur,int pre,const Tree &T)
	  {
	  for(auto nxt:d[cur])if(nxt!=pre)DP(nxt,cur,T);
	  for(const auto &pi:T.mp)
	    {
	    auto &types=pi.second;
	    int id=pi.first,n=types.size(),now=0,lst=1;
	    for(int i=0;i<(1<<n);i++)f[i][0]=f[i][1]=0;
	    f[0][0]=1;
	    for(auto nxt:d[cur])if(nxt!=pre)
	      {
	      now^=1,lst^=1;
	      for(int i=0;i<(1<<n);i++)
	        f[i][now]=f[i][lst];
	      for(int i=0;i<n;i++)
	        if(num[nxt][types[i]])
	          for(int j=(1<<n)-1;j>=0;j--)
	            if(f[j][lst] && !((1<<i)&j) && !(i && types[i]==types[i-1] && !((1<<(i-1))&j)))
	              (f[(1<<i)|j][now]+=1ll*f[j][lst]*num[nxt][types[i]]%MOD)%=MOD;
		  }
		if(f[(1<<n)-1][now])
		  {
		  //cout<<id<<endl;
		  num[cur][id]=f[(1<<n)-1][now];
		  if(len(id)==2*T.n)(ans+=num[cur][id])%=MOD;
		  }
		}
	  }
}S,T;
int main()
{
	S.read();
	T.read();
	T.getID();
	S.DP(1,0,T);
	printf("%d\n",S.ans);
}


#ifdef DEBUG
//#define _GLIBCXX_DEBUG
#endif

#include <bits/stdc++.h>

using namespace std;

typedef long double ld;

#ifdef DEBUG
#define eprintf(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define sz(x) ((int) (x).size())
#define TASK "text"

const int inf = (int) 1.01e9;
const ld eps = 1e-9;
const ld pi = acos((ld) -1);

mt19937 mrand(random_device{} ());

int rnd(int x) {
  return mrand() % x;
}

void precalc() {
}

const int mod = (int) 1e9 + 7;

void add(int &a, int b) {
  a += b;
  if (a >= mod) {
    a -= mod;
  }
}

int mul(int a, int b) {
  return (long long) a * b % mod;
}

pair<int, int> gcd(int a, int b) {
  if (!b) {
    return make_pair(1, 0);
  }
  pair<int, int> p = gcd(b, a % b);
  return make_pair(p.second, p.first - (a / b) * p.second);
}

int inv(int x) {
  int res = gcd(x, mod).first;
  if (res < 0) {
    res += mod;
  }
  return res;
}

const int maxn = 1005, maxm = 13;
int n[2];
vector<int> g[2][maxn];
vector<int> ids[maxm];
int s[3 * maxm], t[3 * maxm];

int read() {
  for (int t = 0; t < 2; t++) {
    if (scanf("%d", &n[t]) < 1) {
      return false;
    }
    for (int i = 0; i < n[t]; i++) {
      g[t][i].clear();
      if (t) {
        ids[i].clear();
      }
    }
    if (t) {
      for (int i = 0; i < n[t]; i++) {
        s[i] = -1;
        ::t[i] = i;
      }
    }
    for (int i = 0; i < n[t] - 1; i++) {
      int v, u;
      scanf("%d%d", &v, &u);
      v--;
      u--;
      g[t][v].push_back(u);
      g[t][u].push_back(v);
      if (t) {
        ids[v].push_back(n[t] + 2 * i);
        ids[u].push_back(n[t] + 2 * i + 1);
        s[n[t] + 2 * i] = v;
        ::t[n[t] + 2 * i] = u;
        s[n[t] + 2 * i + 1] = u;
        ::t[n[t] + 2 * i + 1] = v;
      }
    }
  }
  return true;
}

int dp[maxn][3 * maxm];
int a[maxn][1 << maxm];

void dfs(int v, int p) {
  for (int i = 0; i < sz(g[0][v]); i++) {
    int u = g[0][v][i];
    if (u == p) {
      continue;
    }
    dfs(u, v);
  }
  for (int e = 0; e < n[1] + 2 * (n[1] - 1); e++) {
    vector<int> es;
    for (int i = 0; i < sz(g[1][t[e]]); i++) {
      if (g[1][t[e]][i] != s[e]) {
        es.push_back(ids[t[e]][i]);
      }
    }
    for (int i = 0; i <= sz(g[0][v]); i++) {
      for (int j = 0; j < (1 << sz(es)); j++) {
        a[i][j] = 0;
      }
    }
    a[0][0] = 1;
    for (int i = 0; i < sz(g[0][v]); i++) {
      int u = g[0][v][i];
      if (u == p) {
        for (int j = 0; j < (1 << sz(es)); j++) {
          a[i + 1][j] = a[i][j];
        }
        continue;
      }
      for (int j = 0; j < (1 << sz(es)); j++) {
        auto cur = a[i][j];
        if (!cur) {
          continue;
        }
        add(a[i + 1][j], cur);
        for (int k = 0; k < sz(es); k++) {
          if (j & (1 << k)) {
            continue;
          }
          add(a[i + 1][j | (1 << k)], mul(cur, dp[u][es[k]]));
        }
      }
    }
    dp[v][e] = a[sz(g[0][v])][(1 << sz(es)) - 1];
  }
}

int solve1() {
  dfs(0, -1);
  int res = 0;
  for (int i = 0; i < n[0]; i++) {
    for (int j = 0; j < n[1]; j++) {
      add(res, dp[i][j]);
    }
  }
  return res;
}

void solve() {
  int res = solve1();
  n[0] = n[1];
  for (int i = 0; i < n[0]; i++) {
    g[0][i] = g[1][i];
  }
  res = mul(res, inv(solve1()));
  printf("%d\n", res);
}

int main() {
  precalc();
#ifdef DEBUG
  assert(freopen(TASK ".in", "r", stdin));
  assert(freopen(TASK ".out", "w", stdout));
#endif
  while (read()) {
    solve();
#ifdef DEBUG
    eprintf("Time %.2f\n", (double) clock() / CLOCKS_PER_SEC);
#endif
  }
  return 0;
}


#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif

#include <bits/stdc++.h>

using namespace std;

typedef long double ld;
typedef long long ll;

#ifdef DEBUG
#define eprintf(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define pb push_back
#define mp make_pair
#define sz(x) ((int) (x).size())
#define TASK "text"

const int inf = (int) 1.01e9;
const ld eps = 1e-9;
const ld pi = acos((ld) -1);

mt19937 mrand(random_device{} ());

int rnd(int x) {
  return mrand() % x;
}

void precalc() {
}

const int mod = (int) 1e9 + 7;

void add(int &a, int b) {
  a += b;
  if (a >= mod) {
    a -= mod;
  }
}

int mul(int a, int b) {
  return (long long) a * b % mod;
}

pair<int, int> gcd(int a, int b) {
  if (!b) {
    return make_pair(1, 0);
  }
  pair<int, int> p = gcd(b, a % b);
  return make_pair(p.second, p.first - (a / b) * p.second);
}

int inv(int x) {
  int res = gcd(x, mod).first;
  if (res < 0) {
    res += mod;
  }
  return res;
}

const int maxn = 1005, maxm = 12;
int n, m;
vector<int> g[maxn];
vector<int> gt[maxm];

int read() {
  if (scanf("%d", &n) < 1) {
    return false;
  }
  for (int i = 0; i < n; i++) {
    g[i].clear();
  }
  for (int i = 0; i < n - 1; i++) {
    int v, u;
    scanf("%d%d", &v, &u);
    v--;
    u--;
    g[v].push_back(u);
    g[u].push_back(v);
  }
  scanf("%d", &m);
  for (int i = 0; i < m; i++) {
    gt[i].clear();
  }
  for (int i = 0; i < m - 1; i++) {
    int v, u;
    scanf("%d%d", &v, &u);
    v--;
    u--;
    gt[v].push_back(u);
    gt[u].push_back(v);
  }
  return true;
}

int rt;
vector<int> dp[maxn][maxm];
vector<int> rev[maxn];
int a[maxn][(1 << maxm)];

void dfst(int vt, int pt) {
  for (int i = 0; i < sz(gt[vt]); i++) {
    int ut = gt[vt][i];
    if (ut == pt) {
      swap(gt[vt][i], gt[vt].back());
      gt[vt].pop_back();
      break;
    }
  }
  for (int i = 0; i < sz(gt[vt]); i++) {
    int ut = gt[vt][i];
    dfst(ut, vt);
  }
  if (pt == -1) {
    for (int v = 0; v < n; v++) {
      for (int j = 0; j < sz(g[v]) + 1; j++) {
        for (int k = 0; k < (1 << sz(gt[vt])); k++) {
          a[j][k] = 0;
        }
      }
      a[0][0] = 1;
      for (int j = 0; j < sz(g[v]); j++) {
        for (int msk = 0; msk < (1 << sz(gt[vt])); msk++) {
          if (a[j][msk]) {
            add(a[j + 1][msk], a[j][msk]);
            for (int k = 0; k < sz(gt[vt]); k++) {
              if (msk & (1 << k)) {
                continue;
              }
              add(a[j + 1][msk | (1 << k)], mul(a[j][msk], dp[gt[vt][k]][g[v][j]][rev[v][j]]));
            }
          }
        }
      }
      dp[vt][v] = vector<int>(1, a[sz(g[v])][(1 << sz(gt[vt])) - 1]);
    }
    return;
  }
  for (int v = 0; v < n; v++) {
    dp[vt][v] = vector<int>(sz(g[v]));
    for (int i = 0; i < sz(g[v]); i++) {
      for (int j = 0; j < sz(g[v]) + 1; j++) {
        for (int k = 0; k < (1 << sz(gt[vt])); k++) {
          a[j][k] = 0;
        }
      }
      a[0][0] = 1;
      for (int j = 0; j < sz(g[v]); j++) {
        for (int msk = 0; msk < (1 << sz(gt[vt])); msk++) {
          if (a[j][msk]) {
            add(a[j + 1][msk], a[j][msk]);
            if (j != i) {
              for (int k = 0; k < sz(gt[vt]); k++) {
                if (msk & (1 << k)) {
                  continue;
                }
                add(a[j + 1][msk | (1 << k)], mul(a[j][msk], dp[gt[vt][k]][g[v][j]][rev[v][j]]));
              }
            }
          }
        }
      }
      dp[vt][v][i] = a[sz(g[v])][(1 << sz(gt[vt])) - 1];
    }
  }
}

int gm[maxm][maxm];
int used[maxm];
int p[maxm];

int gen(int pos) {
  if (pos == m) {
    return 1;
  }
  int res = 0;
  for (int i = 0; i < m; i++) {
    if (used[i]) {
      continue;
    }
    bool ok = true;
    for (int j = 0; j < pos; j++) {
      if (gm[pos][j] != gm[i][p[j]]) {
        ok = false;
        break;
      }
    }
    if (!ok) {
      continue;
    }
    p[pos] = i;
    used[i] = true;
    add(res, gen(pos + 1));
    used[i] = false;
  }
  return res;
}

void solve() {
  memset(gm, 0, sizeof(gm));
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < sz(gt[i]); j++) {
      gm[i][gt[i][j]] = true;
    }
  }
  int aut = gen(0);
  rt = 0;
  for (int i = 1; i < m; i++) {
    if (sz(gt[i]) > sz(gt[rt])) {
      rt = i;
    }
  }
  for (int v = 0; v < n; v++) {
    rev[v].resize(sz(g[v]));
    for (int i = 0; i < sz(g[v]); i++) {
      int u = g[v][i];
      for (int j = 0; j < sz(g[u]); j++) {
        if (g[u][j] == v) {
          rev[v][i] = j;
          break;
        }
      }
    }
  }
  dfst(rt, -1);
  int res = 0;
  for (int i = 0; i < n; i++) {
    add(res, dp[rt][i][0]);
  }
  res = mul(res, inv(aut));
  printf("%d\n", res);
}

int main() {
  precalc();
#ifdef LOCAL
  assert(freopen(TASK ".in", "r", stdin));
  assert(freopen(TASK ".out", "w", stdout));
#endif
  while (true) {
    if (!read()) {
      break;
    }
    solve();
#ifdef DEBUG
    eprintf("Time %.2f\n", (double) clock() / CLOCKS_PER_SEC);
#endif
  }
  return 0;
}


#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif

#include <bits/stdc++.h>

using namespace std;

typedef long double ld;
typedef long long ll;

#ifdef DEBUG
#define eprintf(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define pb push_back
#define mp make_pair
#define sz(x) ((int) (x).size())
#define TASK "text"

const int inf = (int) 1.01e9;
const ld eps = 1e-9;
const ld pi = acos((ld) -1);

mt19937 mrand(random_device{} ());

int rnd(int x) {
  return mrand() % x;
}

void precalc() {
}

const int mod = (int) 1e9 + 7;

void add(int &a, int b) {
  a += b;
  if (a >= mod) {
    a -= mod;
  }
}

int mul(int a, int b) {
  return (long long) a * b % mod;
}

pair<int, int> gcd(int a, int b) {
  if (!b) {
    return make_pair(1, 0);
  }
  pair<int, int> p = gcd(b, a % b);
  return make_pair(p.second, p.first - (a / b) * p.second);
}

int inv(int x) {
  int res = gcd(x, mod).first;
  if (res < 0) {
    res += mod;
  }
  return res;
}

const int maxn = 1005, maxm = 12;
int n, m;
vector<int> g[maxn];
vector<int> gt[maxm];

int read() {
  if (scanf("%d", &n) < 1) {
    return false;
  }
  for (int i = 0; i < n; i++) {
    g[i].clear();
  }
  for (int i = 0; i < n - 1; i++) {
    int v, u;
    scanf("%d%d", &v, &u);
    v--;
    u--;
    g[v].push_back(u);
    g[u].push_back(v);
  }
  scanf("%d", &m);
  for (int i = 0; i < m; i++) {
    gt[i].clear();
  }
  for (int i = 0; i < m - 1; i++) {
    int v, u;
    scanf("%d%d", &v, &u);
    v--;
    u--;
    gt[v].push_back(u);
    gt[u].push_back(v);
  }
  return true;
}

int rt;
vector<int> dp[maxn][maxm];
vector<int> rev[maxn];

void dfst(int vt, int pt) {
  for (int i = 0; i < sz(gt[vt]); i++) {
    int ut = gt[vt][i];
    if (ut == pt) {
      swap(gt[vt][i], gt[vt].back());
      gt[vt].pop_back();
      break;
    }
  }
  for (int i = 0; i < sz(gt[vt]); i++) {
    int ut = gt[vt][i];
    dfst(ut, vt);
  }
  if (pt == -1) {
    for (int v = 0; v < n; v++) {
      vector< vector<int> > a(sz(g[v]) + 1, vector<int>((1 << sz(gt[vt])), 0));
      a[0][0] = 1;
      for (int j = 0; j < sz(g[v]); j++) {
        for (int msk = 0; msk < (1 << sz(gt[vt])); msk++) {
          if (a[j][msk]) {
            add(a[j + 1][msk], a[j][msk]);
            for (int k = 0; k < sz(gt[vt]); k++) {
              if (msk & (1 << k)) {
                continue;
              }
              add(a[j + 1][msk | (1 << k)], mul(a[j][msk], dp[g[v][j]][gt[vt][k]][rev[v][j]]));
            }
          }
        }
      }
      dp[v][vt] = vector<int>(1, a[sz(g[v])][(1 << sz(gt[vt])) - 1]);
    }
    return;
  }
  for (int v = 0; v < n; v++) {
    dp[v][vt] = vector<int>(sz(g[v]));
    for (int i = 0; i < sz(g[v]); i++) {
      vector< vector<int> > a(sz(g[v]) + 1, vector<int>((1 << sz(gt[vt])), 0));
      a[0][0] = 1;
      for (int j = 0; j < sz(g[v]); j++) {
        for (int msk = 0; msk < (1 << sz(gt[vt])); msk++) {
          if (a[j][msk]) {
            add(a[j + 1][msk], a[j][msk]);
            if (j != i) {
              for (int k = 0; k < sz(gt[vt]); k++) {
                if (msk & (1 << k)) {
                  continue;
                }
                add(a[j + 1][msk | (1 << k)], mul(a[j][msk], dp[g[v][j]][gt[vt][k]][rev[v][j]]));
              }
            }
          }
        }
      }
      dp[v][vt][i] = a[sz(g[v])][(1 << sz(gt[vt])) - 1];
    }
  }
}

int gm[maxm][maxm];
int used[maxm];
int p[maxm];

int gen(int pos) {
  if (pos == m) {
    return 1;
  }
  int res = 0;
  for (int i = 0; i < m; i++) {
    if (used[i]) {
      continue;
    }
    bool ok = true;
    for (int j = 0; j < pos; j++) {
      if (gm[pos][j] != gm[i][p[j]]) {
        ok = false;
        break;
      }
    }
    if (!ok) {
      continue;
    }
    p[pos] = i;
    used[i] = true;
    add(res, gen(pos + 1));
    used[i] = false;
  }
  return res;
}

void solve() {
  memset(gm, 0, sizeof(gm));
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < sz(gt[i]); j++) {
      gm[i][gt[i][j]] = true;
    }
  }
  int aut = gen(0);
  rt = 0;
  for (int i = 1; i < m; i++) {
    if (sz(gt[i]) > sz(gt[rt])) {
      rt = i;
    }
  }
  for (int v = 0; v < n; v++) {
    rev[v].resize(sz(g[v]));
    for (int i = 0; i < sz(g[v]); i++) {
      int u = g[v][i];
      for (int j = 0; j < sz(g[u]); j++) {
        if (g[u][j] == v) {
          rev[v][i] = j;
          break;
        }
      }
    }
  }
  dfst(rt, -1);
  int res = 0;
  for (int i = 0; i < n; i++) {
    add(res, dp[i][rt][0]);
  }
  res = mul(res, inv(aut));
  printf("%d\n", res);
}

int main() {
  precalc();
#ifdef LOCAL
  assert(freopen(TASK ".in", "r", stdin));
  assert(freopen(TASK ".out", "w", stdout));
#endif
  while (true) {
    if (!read()) {
      break;
    }
    solve();
#ifdef DEBUG
    eprintf("Time %.2f\n", (double) clock() / CLOCKS_PER_SEC);
#endif
  }
  return 0;
}


#ifdef DEBUG
#define _GLIBCXX_DEBUG
#endif

#include <bits/stdc++.h>

using namespace std;

typedef long double ld;
typedef long long ll;

#ifdef DEBUG
#define eprintf(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
#else
#define eprintf(...) ;
#endif

#define pb push_back
#define mp make_pair
#define sz(x) ((int) (x).size())
#define TASK "text"

const int inf = (int) 1.01e9;
const ld eps = 1e-9;
const ld pi = acos((ld) -1);

mt19937 mrand(random_device{} ());

int rnd(int x) {
  return mrand() % x;
}

void precalc() {
}

const int mod = (int) 1e9 + 7;

void add(int &a, int b) {
  a += b;
  if (a >= mod) {
    a -= mod;
  }
}

int mul(int a, int b) {
  return (long long) a * b % mod;
}

pair<int, int> gcd(int a, int b) {
  if (!b) {
    return make_pair(1, 0);
  }
  pair<int, int> p = gcd(b, a % b);
  return make_pair(p.second, p.first - (a / b) * p.second);
}

int inv(int x) {
  int res = gcd(x, mod).first;
  if (res < 0) {
    res += mod;
  }
  return res;
}

const int maxn = 1005, maxm = 12;
int n, m;
vector<int> g[maxn];
vector<int> gt[maxm];

int read() {
  if (scanf("%d", &n) < 1) {
    return false;
  }
  for (int i = 0; i < n; i++) {
    g[i].clear();
  }
  for (int i = 0; i < n - 1; i++) {
    int v, u;
    scanf("%d%d", &v, &u);
    v--;
    u--;
    g[v].push_back(u);
    g[u].push_back(v);
  }
  scanf("%d", &m);
  for (int i = 0; i < m; i++) {
    gt[i].clear();
  }
  for (int i = 0; i < m - 1; i++) {
    int v, u;
    scanf("%d%d", &v, &u);
    v--;
    u--;
    gt[v].push_back(u);
    gt[u].push_back(v);
  }
  return true;
}

int rt;
vector<int> dp[maxm][maxn];
vector<int> rev[maxn];
int a[maxn][(1 << maxm)];

void dfst(int vt, int pt) {
  for (int i = 0; i < sz(gt[vt]); i++) {
    int ut = gt[vt][i];
    if (ut == pt) {
      swap(gt[vt][i], gt[vt].back());
      gt[vt].pop_back();
      break;
    }
  }
  for (int i = 0; i < sz(gt[vt]); i++) {
    int ut = gt[vt][i];
    dfst(ut, vt);
  }
  if (pt == -1) {
    for (int v = 0; v < n; v++) {
      for (int j = 0; j < sz(g[v]) + 1; j++) {
        for (int k = 0; k < (1 << sz(gt[vt])); k++) {
          a[j][k] = 0;
        }
      }
      a[0][0] = 1;
      for (int j = 0; j < sz(g[v]); j++) {
        for (int msk = 0; msk < (1 << sz(gt[vt])); msk++) {
          if (a[j][msk]) {
            add(a[j + 1][msk], a[j][msk]);
            for (int k = 0; k < sz(gt[vt]); k++) {
              if (msk & (1 << k)) {
                continue;
              }
              add(a[j + 1][msk | (1 << k)], mul(a[j][msk], dp[gt[vt][k]][g[v][j]][rev[v][j]]));
            }
          }
        }
      }
      dp[vt][v] = vector<int>(1, a[sz(g[v])][(1 << sz(gt[vt])) - 1]);
    }
    return;
  }
  for (int v = 0; v < n; v++) {
    dp[vt][v] = vector<int>(sz(g[v]));
    for (int i = 0; i < sz(g[v]); i++) {
      for (int j = 0; j < sz(g[v]) + 1; j++) {
        for (int k = 0; k < (1 << sz(gt[vt])); k++) {
          a[j][k] = 0;
        }
      }
      a[0][0] = 1;
      for (int j = 0; j < sz(g[v]); j++) {
        for (int msk = 0; msk < (1 << sz(gt[vt])); msk++) {
          if (a[j][msk]) {
            add(a[j + 1][msk], a[j][msk]);
            if (j != i) {
              for (int k = 0; k < sz(gt[vt]); k++) {
                if (msk & (1 << k)) {
                  continue;
                }
                add(a[j + 1][msk | (1 << k)], mul(a[j][msk], dp[gt[vt][k]][g[v][j]][rev[v][j]]));
              }
            }
          }
        }
      }
      dp[vt][v][i] = a[sz(g[v])][(1 << sz(gt[vt])) - 1];
    }
  }
}

int gm[maxm][maxm];
int used[maxm];
int p[maxm];

int gen(int pos) {
  if (pos == m) {
    return 1;
  }
  int res = 0;
  for (int i = 0; i < m; i++) {
    if (used[i]) {
      continue;
    }
    bool ok = true;
    for (int j = 0; j < pos; j++) {
      if (gm[pos][j] != gm[i][p[j]]) {
        ok = false;
        break;
      }
    }
    if (!ok) {
      continue;
    }
    p[pos] = i;
    used[i] = true;
    add(res, gen(pos + 1));
    used[i] = false;
  }
  return res;
}

void solve() {
  memset(gm, 0, sizeof(gm));
  for (int i = 0; i < m; i++) {
    for (int j = 0; j < sz(gt[i]); j++) {
      gm[i][gt[i][j]] = true;
    }
  }
  int aut = gen(0);
  rt = 0;
  for (int i = 1; i < m; i++) {
    if (sz(gt[i]) > sz(gt[rt])) {
      rt = i;
    }
  }
  for (int v = 0; v < n; v++) {
    rev[v].resize(sz(g[v]));
    for (int i = 0; i < sz(g[v]); i++) {
      int u = g[v][i];
      for (int j = 0; j < sz(g[u]); j++) {
        if (g[u][j] == v) {
          rev[v][i] = j;
          break;
        }
      }
    }
  }
  dfst(rt, -1);
  int res = 0;
  for (int i = 0; i < n; i++) {
    add(res, dp[rt][i][0]);
  }
  res = mul(res, inv(aut));
  printf("%d\n", res);
}

int main() {
  precalc();
#ifdef LOCAL
  assert(freopen(TASK ".in", "r", stdin));
  assert(freopen(TASK ".out", "w", stdout));
#endif
  while (true) {
    if (!read()) {
      break;
    }
    solve();
#ifdef DEBUG
    eprintf("Time %.2f\n", (double) clock() / CLOCKS_PER_SEC);
#endif
  }
  return 0;
}


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <set>

const int MAXN = 1010;
const int MAXS = 1 << 12;
const int Dollar1 = 1000000007;
typedef long long LL;
typedef std::vector<int> VI;
typedef std::set<int> SI;
inline int up(int x) { return x -= Dollar1, x + (x >> 31 & Dollar1); }
inline int down(const int x) { return x + (x >> 31 & Dollar1); }
inline void add(int & x, const int y) { x += y - Dollar1, x += x >> 31 & Dollar1; }
inline void dec(int & x, const int y) { x -= y, x += x >> 31 & Dollar1; }
inline int mul(const int x, const int y) {
	return static_cast<LL> (x) * y % Dollar1;
}
inline void mulr(int & x, const int y) {
	x = static_cast<LL> (x) * y % Dollar1;
}
int head[MAXN], nxt[MAXN << 1], to[MAXN << 1], tot;
inline void addedge(int b, int e) {
	nxt[++tot] = head[b]; to[head[b] = tot] = e;
	nxt[++tot] = head[e]; to[head[e] = tot] = b;
}
struct T {
	int head[12], nxt[12 << 1], to[12 << 1], tot;
	T() { memset(head, 0, sizeof head); tot = 0; }
	inline void addedge(int b, int e) {
		nxt[++tot] = head[b]; to[head[b] = tot] = e;
		nxt[++tot] = head[e]; to[head[e] = tot] = b;
	}
} tree;
int fac[20], inv[20];
int ha[13], rdc[13], fa[13];
VI has[13];
int getha(int u, int f) {
	fa[u] = f;
	VI & hal = has[u]; hal.clear();
	for (int i = tree.head[u]; i; i = tree.nxt[i]) if (tree.to[i] != f)
		hal.push_back(getha(tree.to[i], u));
	std::sort(hal.begin(), hal.end());
	int vha = 0, now = 13, lst = -1, cnt = 1, red = 1;
	for (int i : hal) {
		if (i == lst) ++cnt; else mulr(red, inv[cnt]), cnt = 1, lst = i;
		add(vha, mul(now, i)), mulr(now, 41);
	}
	mulr(red, inv[cnt]);
	add(vha, 1); rdc[u] = red;
	// printf("GETHA %d FA %d RDC %d HA %d , LI : ", u, f, rdc[u], vha);
	// for (int i : hal) printf("%d ", i);
	// putchar(10);
	return ha[u] = vha;
}
int n, m, t1, t2;
int dp[MAXN][12];
int cnt[1 << 12];
SI vis;
int ans = 0;
int avai[12], RT;
void DP(int u, int f) {
	for (int i = head[u]; i; i = nxt[i]) if (to[i] != f) DP(to[i], u);
	// printf("DP %d\n", u);
	for (int i = 0; i != m; ++i) {
		memset(avai, -1, sizeof avai);
		int bak = 0;
		for (int j = tree.head[i]; j; j = tree.nxt[j])
			if (tree.to[j] != fa[i]) avai[tree.to[j]] = bak++;
		const int U = 1 << bak;
		memset(cnt, 0, U << 2);
		cnt[0] = 1;
		for (int j = head[u]; j; j = nxt[j]) if (to[j] != f) {
			for (int k = U - 2; k >= 0; --k) if (cnt[k]) {
				for (int l = 0; l != m; ++l)
					if (~avai[l] && !(k >> avai[l] & 1))
						add(cnt[k | 1 << avai[l]], mul(cnt[k], dp[to[j]][l]));
			}
		}
		// printf("DP RT %d : ", i);
		// for (int j = 0; j != m; ++j) if (~avai[j]) prin
		// for (int j = 0; j != U; ++j) printf("%d ", cnt[j]); putchar(10);
		dp[u][i] = mul(cnt[U - 1], rdc[i]);
	}
	// printf("GET : "); for (int i = 0; i != m; ++i) printf("%d ", dp[u][i]);
	// putchar(10);
	add(ans, dp[u][RT]);
}
int main() {
	fac[0] = fac[1] = inv[0] = inv[1] = 1;
	for (int i = 2; i != 20; ++i) {
		fac[i] = mul(fac[i - 1], i);
		inv[i] = mul(inv[Dollar1 % i], down(-Dollar1 / i));
	}
	for (int i = 2; i != 20; ++i) mulr(inv[i], inv[i - 1]);
	scanf("%d", &n);
	for (int i = 1; i != n; ++i) {
		scanf("%d%d", &t1, &t2);
		addedge(t1, t2);
	}
	scanf("%d", &m);
	for (int i = 1; i != m; ++i) {
		scanf("%d%d", &t1, &t2);
		tree.addedge(--t1, --t2);
	}
	for (int i = 0; i != m; ++i) {
		int HA = getha(i, -1);
		if (vis.find(HA) != vis.end()) continue;
		vis.insert(HA);
		memset(dp, 0, sizeof dp);
		RT = i;
		DP(1, 0);
	}
	printf("%d\n", ans);
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef bool boolean;

const int N = 1e3 + 5, M = 12, S = 1 << (M - 1);
const int Mod = 1e9 + 7;

void exgcd(int a, int b, int& x, int& y) {
	if (!b) {
		x = 1, y = 0;
	} else {
		exgcd(b, a % b, y, x);
		y -= (a / b) * x;
	}
}

int inv(int a) {
	int x, y;
	exgcd(a, Mod, x, y);
	return (x < 0) ? (x + Mod) : (x);
}

int add(int a, int b) {
	return ((a += b) >= Mod) ? (a - Mod) : (a);
}

int n, m;
int deg[M];
int u[M], v[M];
vector<int> id[M];
vector<int> G1[N], G2[M];

#define RT(x) (((m - 1) << 1) + x + 1)
// 0 ~ 2m - 2: edge (u, v), u as father;
// 2m - 1 ~ 3m - 2: (i - (2m - 1)) as root
int f[N][M * 3], g[S];
template <vector<int> G[]>
void dfs(int p, int fa, int& ans) {
	for (auto& e : G[p]) {
		if (e ^ fa) {
			dfs<G>(e, p, ans);
		}
	}
	for (int r = 0; r < m; r++) {
		int full = 1 << deg[r];
		memset(g, 0, full << 2);
		g[0] = 1;
		for (auto& e : G[p]) {
			if (e == fa) {
				continue;
			}
			for (int s = full - 1; s; s--) {
				for (int i = 0, x; i < deg[r]; i++) {
					if ((s >> i) & 1) {
						x = id[r][i];
						g[s] = (g[s] + g[s ^ (1 << i)] * 1ll * f[e][x]) % Mod;
					}
				}
			}
		}
		ans = add(ans, f[p][RT(r)] = g[--full]);
		for (int i = 0; i < deg[r]; i++) {
			f[p][id[r][i] ^ 1] = g[full ^ (1 << i)];
		}
	}
}

int main() {
	scanf("%d", &n);
	for (int i = 1, u, v; i < n; i++) {
		scanf("%d%d", &u, &v);
		--u, --v;
		G1[u].push_back(v);
		G1[v].push_back(u);
	}
	scanf("%d", &m);
	for (int i = 0, u, v; i < m - 1; i++) {
		scanf("%d%d", &u, &v);
		deg[--u]++, deg[--v]++;
		G2[u].push_back(v);
		G2[v].push_back(u);
		id[u].push_back((i << 1));
		id[v].push_back((i << 1) | 1);
	}
	int a = 0, b = 0;
	dfs<G1>(0, -1, a);
	dfs<G2>(0, -1, b);
	a = 1ll * a * inv(b) % Mod;
	printf("%d\n", a);
	return 0;
}


#include <algorithm>
#include <cstdio>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
const int N = 1010;
const int mod = 1e9 + 7;
int na, nb;
vector<int>ga[N], gb[N];
namespace _prime{
    int d[N], a[N];
    void init() {
        for (int i = 2; i < N ; i ++) {
            if (!a[i])
                d[a[i] = ++d[0]] = i;
            for (int j = 1; j <= a[i] && 1ll * d[j] * i < N; j ++)
                a[d[j] * i] = j;
        }
    }
}
int randseed;
int rk_p(int rk){
    return _prime::d[rk + 1] * randseed;
}
int add(int x, int y) {
    x+= y;
    return x >= mod ?x - mod : x;
}
int sub(int x, int y) {
    x -= y;
    return x < 0 ? x +mod : x;
}
int mul(int x, int y){
    return 1ll * x * y % mod;
}
int calc(int x, int y) {
    int z = 1;
    while (y) {
        if (y & 1) z = mul(z, x);
        x = mul(x, x), y >>= 1;
    }
    return z;
}
int tot_status = 0;
pair<long long, int> status_list_all[4000];
int s_s_update[4000][4000];
map<pair<long long, int>, int> m_all;
int update(long long v, int sz) {
    if (m_all.find(make_pair(v, sz)) == m_all.end()) {
        status_list_all[++tot_status] = make_pair(v, sz);
        m_all[make_pair(v, sz)] = tot_status;
    }
    return m_all[make_pair(v,sz)];
}
int f[1001][4000];
int tmp[4000];
vector<pair<int, int> > can_merge;
int ans = 0;
vector<int> match_status;
void dfs(int x, int fa) {
    f[x][1] = 1;
    for (auto v:ga[x])
        if (v != fa) {
            dfs(v, x);
            for (auto u:can_merge)
                tmp[s_s_update[u.first][u.second]] = add(tmp[s_s_update[u.first][u.second]], mul(f[x][u.first], f[v][u.second]));
            for (int i = 1; i <= tot_status; i ++)
                f[x][i] = add(tmp[i], f[x][i]), tmp[i] = 0;
        }
    int last = 0;
    for (auto u:match_status)
        if (last != u)
            ans = add(ans, f[x][u]), last =u;
}
pair<long long,int> dfs1(int x, int fa) {
    long long v = 1;
    int sz = 1;
    for (auto u:gb[x])
        if (u != fa) {
            auto w = dfs1(u, x);
            v = v + w.first * rk_p(w.second);
            sz += w.second;
        }
    return make_pair(v, sz);
}
map<long long, int> can;

#include <ctime>
int main() {
    _prime::init();
    srand(time(0));
    randseed = rand() % 10000 + 1;
    update(1, 1);
    scanf("%d", &na);
    for (int i = 1; i < na; i ++) {
        int x, y;
        scanf("%d%d", &x, &y);
        ga[x].push_back(y);
        ga[y].push_back(x);
    }

    scanf("%d", &nb);
    for (int i = 1; i < nb; i ++) {
        int x, y;
        scanf("%d%d", &x, &y);
        gb[x].push_back(y);
        gb[y].push_back(x);
    }
    for (int i = 1; i <= nb; i ++) {
        auto v = dfs1(i, 0);
        can[v.first] = 1;
    }
    for (int v = 2; v <= 12; v ++)
        for (int i = 1; i <= tot_status; i ++)
            for (int j = 1;j <= tot_status; j ++)
                if (status_list_all[i].second + status_list_all[j].second == v && !(v == 12 && !can[status_list_all[i].first + status_list_all[j].first * rk_p(status_list_all[j].second)])) {
                    int u = update(status_list_all[i].first + status_list_all[j].first * rk_p(status_list_all[j].second) , status_list_all[i].second + status_list_all[j].second );
                    s_s_update[i][j] = u;
                    can_merge.push_back(make_pair(i, j));
                }
    for (auto u:can)
        if (u.second)
            match_status.push_back(update(u.first, nb));
    sort(match_status.begin(), match_status.end());
    dfs(1, 0);
    printf("%d\n", ans);
    return 0;
}
 	  	   	 		 	   	 	  	 	  	//hello


#include<bits/stdc++.h>
#define ll long long
#define inl inline
using namespace std;
const int N=1005;
const ll mo=1e9+7;
struct edg{
	int to,nxt;
};
struct tree{
	edg e[N<<1];
	int siz[N],bit[N],son[N][N],head[N],n,cnt;
	inl void add(int u,int v)
	{
		cnt++;
		e[cnt].to=v;
		e[cnt].nxt=head[u];
		head[u]=cnt;
	}
	inl void read()
	{
		scanf("%d",&n);
		for(int i=1;i<n;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			add(v,u);
			add(u,v);
		}
	}
	void dfs(int u,int f)
	{
		siz[u]=bit[u]=0;
		for(int i=head[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			if(v==f)continue;
			son[u][++siz[u]]=v;
			dfs(v,u);
			bit[u]|=1<<(v-1);
		}
	}
}S,T;
ll getinv(int x)
{
	return x<=1? 1:(ll)(mo-mo/x)*getinv(mo%x)%mo;
}
ll dp[N][N*5],ans1,ans2;
bool vis[N][N*5];
ll dfs(int u,int id,int s)
{
	if(!id)return s==0;
	int x=S.son[u][id];
	if(vis[x][s])return dp[x][s];
	ll sum=dfs(u,id-1,s);
	for(int i=0;i<T.n;i++)
		if(s>>i&1)
			sum=(sum+dfs(u,id-1,s^(1<<i))*dfs(x,S.siz[x],T.bit[i+1])%mo)%mo;
	return dp[x][s]=sum;
}
int main()
{
	S.read(),T.read();
	S.dfs(1,0);
	for(int i=1;i<=T.n;i++)
	{
		memset(vis,0,sizeof(vis));
		memset(dp,0,sizeof(dp));
		T.dfs(i,0);
		for(int j=1;j<=S.n;j++)
			ans1=(ans1+dfs(j,S.siz[j],T.bit[i]));
	}
	S=T;
	S.dfs(1,0);
	for(int i=1;i<=T.n;i++)
	{
		memset(vis,0,sizeof(vis));
		memset(dp,0,sizeof(dp));
		T.dfs(i,0);
		for(int j=1;j<=S.n;j++)
			ans2=(ans2+dfs(j,S.siz[j],T.bit[i]));
	}
	ll ans=ans1*getinv(ans2)%mo;
	printf("%lld",ans);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define inl inline
using namespace std;
const int N=1005;
const ll mo=1e9+7;
struct edg{
	int to,nxt;
};
struct tree{
	edg e[N<<1];
	int siz[N],bit[N],son[N][N],head[N],n,cnt;
	inl void add(int u,int v)
	{
		cnt++;
		e[cnt].to=v;
		e[cnt].nxt=head[u];
		head[u]=cnt;
	}
	inl void read()
	{
		scanf("%d",&n);
		for(int i=1;i<n;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			add(v,u);
			add(u,v);
		}
	}
	void dfs(int u,int f)
	{
		siz[u]=bit[u]=0;
		for(int i=head[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			if(v==f)continue;
			son[u][++siz[u]]=v;
			dfs(v,u);
			bit[u]|=1<<(v-1);
		}
	}
}S,T;
ll getinv(int x)
{
	return x<=1? 1:(ll)(mo-mo/x)*getinv(mo%x)%mo;
}
ll dp[N][N*5],ans1,ans2;
bool vis[N][N*5];
ll dfs(int u,int id,int s)
{
	if(!id)return s==0;
	int x=S.son[u][id];
	if(vis[x][s])return dp[x][s];
	ll sum=dfs(u,id-1,s);
	for(int i=0;i<T.n;i++)
		if(s>>i&1)
			sum=(sum+dfs(u,id-1,s^(1<<i))*dfs(x,S.siz[x],T.bit[i+1])%mo)%mo;
	return dp[u][s]=sum;
}
int main()
{
	S.read(),T.read();
	S.dfs(1,0);
	for(int i=1;i<=T.n;i++)
	{
		memset(vis,0,sizeof(vis));
		memset(dp,0,sizeof(dp));
		T.dfs(i,0);
		for(int j=1;j<=S.n;j++)
			ans1=(ans1+dfs(j,S.siz[j],T.bit[i]));
	}
	S=T;
	S.dfs(1,0);
	for(int i=1;i<=T.n;i++)
	{
		memset(vis,0,sizeof(vis));
		memset(dp,0,sizeof(dp));
		T.dfs(i,0);
		for(int j=1;j<=S.n;j++)
			ans2=(ans2+dfs(j,S.siz[j],T.bit[i]));
	}
	ll ans=ans1*getinv(ans2)%mo;
	printf("%lld",ans);
	return 0;
}


#include<bits/stdc++.h>//Ê÷¹þÏ£+×´Ñ¹+¼ÇËÑ
#define ll long long
#define inl inline
using namespace std;
const int N=1005;
const ll mo=1e9+7;
struct edg{
	int to,nxt;
};
struct tree{
	edg e[N<<1];
	int siz[N],bit[N],son[N][N],head[N],n,cnt;
	inl void add(int u,int v)
	{
		cnt++;
		e[cnt].to=v;
		e[cnt].nxt=head[u];
		head[u]=cnt;
	}
	inl void read()
	{
		scanf("%d",&n);
		for(int i=1;i<n;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			add(v,u);
			add(u,v);
		}
	}
	void dfs(int u,int f)
	{
		siz[u]=bit[u]=0;
		for(int i=head[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			if(v==f)continue;
			son[u][++siz[u]]=v;
			dfs(v,u);
			bit[u]|=1<<v-1;
		}
	}
}S,T;
int getinv(int x)
{
	int y=mo-2;ll s=1;
	while(y)
	{
		if(y&1)s=s*x%mo;
		x=x*x%mo;
		y>>=1;
	 }
	 return (int)s;
}
int dp[N][N*5],ans1,ans2;
bool vis[N][N*5];
int dfs(int u,int id,int s)
{
	if(!id)return !s;
	int x=S.son[u][id];
	if(vis[x][s])return dp[x][s];
	int sum=dfs(u,id-1,s);
	for(int i=0;i<T.n;i++)
		if(s>>i&1)
			sum=(1LL*dfs(u,id-1,s^(1<<i))*dfs(x,S.siz[x],T.bit[i+1])%mo+sum)%mo;
	return dp[x][s]=sum;
}
int main()
{
	S.read(),T.read();
	S.dfs(1,0);
	for(int i=1;i<=T.n;i++)
	{
		memset(vis,0,sizeof(vis));
		memset(dp,0,sizeof(dp));
		T.dfs(i,0);
		for(int j=1;j<=S.n;j++)
			ans1=(ans1+dfs(j,S.siz[j],T.bit[i]));
	}
	S=T;
	S.dfs(1,0);
	for(int i=1;i<=T.n;i++)
	{
		memset(vis,0,sizeof(vis));
		memset(dp,0,sizeof(dp));
		T.dfs(i,0);
		for(int j=1;j<=S.n;j++)
			ans2=(ans2+dfs(j,S.siz[j],T.bit[i]));
	}
	ll ans=ans1*getinv(ans2)%mo;
	printf("%lld",ans);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define inl inline
using namespace std;
const int N=1005;
const ll mo=1e9+7;
struct edg{
	int to,nxt;
};
struct tree{
	edg e[N<<1];
	int siz[N],bit[N],son[N][N],head[N],n,cnt;
	inl void add(int u,int v)
	{
		cnt++;
		e[cnt].to=v;
		e[cnt].nxt=head[u];
		head[u]=cnt;
	}
	inl void read()
	{
		scanf("%d",&n);
		for(int i=1;i<n;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			add(v,u);
			add(u,v);
		}
	}
	void dfs(int u,int f)
	{
		siz[u]=bit[u]=0;
		for(int i=head[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			if(v==f)continue;
			son[u][++siz[u]]=v;
			dfs(v,u);
			bit[u]|=1<<(v-1);
		}
	}
}S,T;
ll getinv(int x)
{
	return x<=1? 1:(ll)(mo-mo/x)*getinv(mo%x)%mo;
}
const int M=(1<<12)+5;
ll dp[N][M],ans1,ans2;
bool vis[N][M];
ll dfs(int u,int id,int s)
{
	if(!id)return s==0;
	int x=S.son[u][id];
	if(vis[x][s])return dp[x][s];
	ll &sum=dp[x][s];
	sum=dfs(u,id-1,s);
	for(int i=0;i<T.n;i++)
		if(s>>i&1)
			sum=(sum+dfs(u,id-1,s^(1<<i))*dfs(x,S.siz[x],T.bit[i+1])%mo)%mo;
	return sum;
}
int main()
{
	S.read(),T.read();
	S.dfs(1,0);
	for(int i=1;i<=T.n;i++)
	{
		memset(vis,0,sizeof(vis));
		memset(dp,0,sizeof(dp));
		T.dfs(i,0);
		for(int j=1;j<=S.n;j++)
			ans1=(ans1+dfs(j,S.siz[j],T.bit[i]))%mo;
	}
	S=T;
	S.dfs(1,0);
	for(int i=1;i<=T.n;i++)
	{
		memset(vis,0,sizeof(vis));
		memset(dp,0,sizeof(dp));
		T.dfs(i,0);
		ans2=(ans2+dfs(1,S.siz[1],T.bit[i]))%mo;
	}
	ll ans=ans1*getinv(ans2)%mo;
	printf("%lld",ans);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define inl inline
using namespace std;
const int N=1005;
const ll mo=1e9+7;
struct edg{
	int to,nxt;
};
struct tree{
	edg e[N<<1];
	int siz[N],bit[N],son[N][N],head[N],n,cnt;
	inl void add(int u,int v)
	{
		cnt++;
		e[cnt].to=v;
		e[cnt].nxt=head[u];
		head[u]=cnt;
	}
	inl void read()
	{
		scanf("%d",&n);
		for(int i=1;i<n;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			add(v,u);
			add(u,v);
		}
	}
	void dfs(int u,int f)
	{
		siz[u]=bit[u]=0;
		for(int i=head[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			if(v==f)continue;
			son[u][++siz[u]]=v;
			dfs(v,u);
			bit[u]|=1<<(v-1);
		}
	}
}S,T;
ll getinv(int x)
{
	return x<=1? 1:(ll)(mo-mo/x)*getinv(mo%x)%mo;
}
const int M=(1<<12)+5;
ll dp[N][M],ans1,ans2;
bool vis[N][M];
/*ll dfs(int u,int id,int s)
{
	if(!id)return s==0;
	int x=S.son[u][id];
	if(vis[x][s])return dp[x][s];
	ll &sum=dp[x][s];
	sum=dfs(u,id-1,s);
	for(int i=0;i<T.n;i++)
		if(s>>i&1)
			sum=(sum+dfs(u,id-1,s^(1<<i))*dfs(x,S.siz[x],T.bit[i+1])%mo)%mo;
	return sum;
}*/
int dfs(int f, int y, int V)
{
	if (!y)
		return !V;
	int x = S.son[f][y];
	if (vis[x][V])
		return dp[x][V];
	vis[x][V] = 1;
	ll &ret = dp[x][V];
	ret = dfs(f, y - 1, V);
	for (int i = 0; i < T.n; i++)
		if (V >> i & 1)
			ret = (1ll * dfs(f, y - 1, V ^ (1 << i)) * dfs(x, S.siz[x], T.bit[i + 1]) + ret) % mo;
	return ret;
}
int main()
{
	S.read(),T.read();
	S.dfs(1,0);
	for(int i=1;i<=T.n;i++)
	{
		memset(vis,0,sizeof(vis));
		memset(dp,0,sizeof(dp));
		T.dfs(i,0);
		for(int j=1;j<=S.n;j++)
			ans1=(ans1+dfs(j,S.siz[j],T.bit[i]))%mo;
	}
	S=T;
	S.dfs(1,0);
	for(int i=1;i<=T.n;i++)
	{
		memset(vis,0,sizeof(vis));
		memset(dp,0,sizeof(dp));
		T.dfs(i,0);
		ans2=(ans2+dfs(1,S.siz[1],T.bit[i]))%mo;
	}
	ll ans=ans1*getinv(ans2)%mo;
	printf("%lld",ans);
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define inl inline
using namespace std;
const int N=1005;
const ll mo=1e9+7;
struct edg{
	int to,nxt;
};
struct tree{
	edg e[N<<1];
	int siz[N],bit[N],son[N][N],head[N],n,cnt;
	inl void add(int u,int v)
	{
		cnt++;
		e[cnt].to=v;
		e[cnt].nxt=head[u];
		head[u]=cnt;
	}
	inl void read()
	{
		scanf("%d",&n);
		for(int i=1;i<n;i++)
		{
			int u,v;
			scanf("%d%d",&u,&v);
			add(v,u);
			add(u,v);
		}
	}
	void dfs(int u,int f)
	{
		siz[u]=bit[u]=0;
		for(int i=head[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			if(v==f)continue;
			son[u][++siz[u]]=v;
			dfs(v,u);
			bit[u]|=1<<(v-1);
		}
	}
}S,T;
ll getinv(int x)
{
	return x<=1? 1:(ll)(mo-mo/x)*getinv(mo%x)%mo;
}
const int M=(1<<12)+5;
ll dp[N][M],ans1,ans2;
bool vis[N][M];
ll dfs(int u,int id,int s)
{
	if(!id)return !s;
	int x=S.son[u][id];
	if(vis[x][s])return dp[x][s];
	vis[x][s]=1;
	ll &sum=dp[x][s];
	sum=dfs(u,id-1,s);
	for(int i=0;i<T.n;i++)
		if(s>>i&1)
			sum=(sum+dfs(u,id-1,s^(1<<i))*dfs(x,S.siz[x],T.bit[i+1])%mo)%mo;
	return sum;
}
int main()
{
	S.read(),T.read();
	S.dfs(1,0);
	for(int i=1;i<=T.n;i++)
	{
		memset(vis,0,sizeof(vis));
		memset(dp,0,sizeof(dp));
		T.dfs(i,0);
		for(int j=1;j<=S.n;j++)
			ans1=(ans1+dfs(j,S.siz[j],T.bit[i]))%mo;
	}
	S=T;
	S.dfs(1,0);
	for(int i=1;i<=T.n;i++)
	{
		memset(vis,0,sizeof(vis));
		memset(dp,0,sizeof(dp));
		T.dfs(i,0);
		ans2=(ans2+dfs(1,S.siz[1],T.bit[i]))%mo;
	}
	ll ans=ans1*getinv(ans2)%mo;
	printf("%lld",ans);
	return 0;
}


#include<bits/stdc++.h>
#include<ctime>
#include<random>
#include<unordered_map>
using namespace std;

#define MAX 1002

vector<int> T[12];
vector<int> S[MAX];
int s;
int t;

#define MOD 1000000007

long long int val[12];

map<int, vector<int> > mp;
int H[MAX];
inline long long int dfs_T(int b,int pr=-1,int d=0){
	long long int r = 1;
	vector<int> vals;
	for (int go : T[b]){
		if (go != pr){
			int U = dfs_T(go, b, d + 1);
			vals.push_back(U);
			r*=(val[d]+U);
			if (r >= MOD)r %= MOD;
		}
	}
	sort(vals.begin(), vals.end());
	if (mp.count(r) == 0){
		mp[r] = vals;
	}
	H[b] = r;
	return r;
}

unordered_map<int, int> dp[MAX];

long long int tmp[MAX];

inline void dfs_S(int b,int pr){
	vector<int> cd;
	for (int go : S[b]){
		if (go != pr){
			dfs_S(go, b);
			cd.emplace_back(go);
		}
	}
	for (auto &it : mp){
		if (it.second.size() > cd.size())continue;
		int sz = it.second.size();
		fill(tmp, tmp + (1 << sz), 0);
		tmp[0] = 1;
		for (int go : cd){
			for (int i = (1<<sz)-1; i>=0; i--){
				for (int j = 0; j < sz; j++){
					if ((i >> j) & 1)continue;
					if (j && (((i >> (j - 1)) & 1) == 0) && it.second[j] == it.second[j - 1])continue;
					tmp[i | (1 << j)] += tmp[i] * dp[go][it.second[j]];
					if (tmp[i | (1 << j)] >= MOD){
						tmp[i | (1 << j)] %= MOD;
					}
				}
			}
		}
		dp[b][it.first] = tmp[(1 << sz) - 1];
	}
}
set<int> all;
int main(){
	cin >> s;
	for (int i = 1; i < s; i++){
		int a, b;
		scanf("%d%d", &a, &b);
		a--;
		b--;
		S[a].push_back(b);
		S[b].push_back(a);
	}
	cin >> t;
	for (int i = 1; i < t; i++){
		int a, b;
		scanf("%d%d", &a, &b);
		a--;
		b--;
		T[a].push_back(b);
		T[b].push_back(a);
	}
	mt19937 mt(time(NULL));
	uniform_int_distribution<int> uf(0, MOD - 1);
	for (int i = 0; i < 12; i++){
		val[i] = uf(mt);
	}
	for (int i = 0; i < t; i++){
		dfs_T(i, -1,0);
		all.insert(H[i]);
	}
	dfs_S(0,-1);
	int ans = 0;
	for (int i = 0; i < s; i++){
		for (int k : all){
			ans += dp[i][k];
			if (ans >= MOD)ans -= MOD;
		}
	}
	cout << ans << endl;
	return 0;
}


#include<bits/stdc++.h>
#include<ctime>
#include<random>
#include<unordered_map>
using namespace std;

#define MAX 1002

vector<int> T[12];
vector<int> S[MAX];
int s;
int t;

#define MOD 1000000007

long long int val[12];

map<int, vector<int> > mp;
int H[MAX];
inline long long int dfs_T(int b,int pr=-1,int d=0){
	long long int r = 1;
	vector<int> vals;
	for (int go : T[b]){
		if (go != pr){
			int U = dfs_T(go, b, d + 1);
			vals.push_back(U);
			r*=(val[d]+U);
			if (r >= MOD)r %= MOD;
		}
	}
	sort(vals.begin(), vals.end());
	if (mp.count(r) == 0){
		mp[r] = vals;
	}
	H[b] = r;
	return r;
}

unordered_map<int, int> dp[MAX];

long long int tmp[1<<12];

inline void dfs_S(int b,int pr){
	vector<int> cd;
	for (int go : S[b]){
		if (go != pr){
			dfs_S(go, b);
			cd.emplace_back(go);
		}
	}
	for (auto &it : mp){
		if (it.second.size() > cd.size())continue;
		int sz = it.second.size();
		fill(tmp, tmp + (1 << sz), 0);
		tmp[0] = 1;
		for (int go : cd){
			for (int i = (1<<sz)-1; i>=0; i--){
				for (int j = 0; j < sz; j++){
					if ((i >> j) & 1)continue;
					if (j && (((i >> (j - 1)) & 1) == 0) && it.second[j] == it.second[j - 1])continue;
					tmp[i | (1 << j)] += tmp[i] * dp[go][it.second[j]];
					if (tmp[i | (1 << j)] >= MOD){
						tmp[i | (1 << j)] %= MOD;
					}
				}
			}
		}
		dp[b][it.first] = tmp[(1 << sz) - 1];
	}
}
set<int> all;
int main(){
	cin >> s;
	for (int i = 1; i < s; i++){
		int a, b;
		scanf("%d%d", &a, &b);
		a--;
		b--;
		S[a].push_back(b);
		S[b].push_back(a);
	}
	cin >> t;
	for (int i = 1; i < t; i++){
		int a, b;
		scanf("%d%d", &a, &b);
		a--;
		b--;
		T[a].push_back(b);
		T[b].push_back(a);
	}
	mt19937 mt(time(NULL));
	uniform_int_distribution<int> uf(0, MOD - 1);
	for (int i = 0; i < 12; i++){
		val[i] = uf(mt);
	}
	for (int i = 0; i < t; i++){
		dfs_T(i, -1,0);
		all.insert(H[i]);
	}
	dfs_S(0,-1);
	int ans = 0;
	for (int i = 0; i < s; i++){
		for (int k : all){
			ans += dp[i][k];
			if (ans >= MOD)ans -= MOD;
		}
	}
	cout << ans << endl;
	return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define N 2005
#define M 15

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

const ll mod=1e9+7;
int n,m;
ll f[N][M];
struct road {int to,next;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}
vector<int>e[N];
ll fac[N],ifac[N];
ll ksm(ll t,ll x) {
	ll ans=1;
	for(;x;x>>=1,t=t*t%mod)
		if(x&1) ans=ans*t%mod;
	return ans;
}

ll Hash[N];
const ll p=2017;
int size[N];
bool cmp(int a,int b) {
	if(size[a]!=size[b]) return size[a]<size[b];
	return Hash[a]<Hash[b];
}

ll t[N];
vector<int>sn[N];
void dfs1(int v,int fr) {
	size[v]=1;
	for(int i=0;i<e[v].size();i++) {
		int to=e[v][i];
		if(to==fr) continue ;
		sn[v].push_back(to);
		dfs1(to,v);
		size[v]+=size[to];
	}
	sort(sn[v].begin(),sn[v].end(),cmp);
	t[v]=1;
	for(int i=0;i<sn[v].size();i++) {
		int j=i;
		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]) j++;
		t[v]=t[v]*ifac[j-i+1]%mod;
		i=j;
	}
	for(int i=0;i<sn[v].size();i++) Hash[v]=(Hash[v]*p+Hash[sn[v][i]])%mod;
	Hash[v]=(Hash[v]*p+size[v])%mod;
}

int Mod(int a) {return a<mod?a:a-mod;}
int st[N],top;
int cal(int v,int u) {
	if(!top) return 0;
	static ll ans[1<<13],g[1<<13];
	int num=sn[u].size();
	for(int i=0;i<1<<num;i++) ans[i]=0;
	ans[0]=1;
	for(int i=1;i<=top;i++) {
		memcpy(g,ans,sizeof(g));
		int now=st[i];
		for(int j=0;j<num;j++) {
			if(!f[now][sn[u][j]]) continue ;
			int t=1<<j;
			for(int sta=0;sta<1<<num;sta++) {
				if(!(sta&t)) g[sta|t]=(g[sta|t]+ans[sta]*f[now][sn[u][j]])%mod;
			}
		}
		memcpy(ans,g,sizeof(g));
	}
	return ans[(1<<num)-1]*t[u]%mod;
}

ll ans;
int rt;
void solve(int v,int fr) {
	for(int i=1;i<=m;i++) if(sn[i].size()==0) f[v][i]=1;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		solve(to,v);
	}
	top=0;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		st[++top]=to;
	}
	for(int i=1;i<=m;i++) {
		if(sn[i].size()) {
			f[v][i]=cal(v,i);
		}
	}
	(ans+=f[v][rt])%=mod;
}

map<int,int>vis;
int work() {
	for(int i=1;i<=m;i++) sn[i].clear();
	memset(Hash,0,sizeof(Hash));
	dfs1(rt,0);
	if(vis.find(Hash[rt])!=vis.end()) return 0;
	vis[Hash[rt]]=1;
	memset(f,0,sizeof(f));
	ans=0;
	solve(1,0);
	return ans;
}

int main() {
	n=Get();
	int a,b;
	for(int i=1;i<n;i++) {
		a=Get(),b=Get();
		add(a,b),add(b,a);
	}
	m=Get();
	fac[0]=1;
	for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;
	ifac[m]=ksm(fac[m],mod-2);
	for(int i=m-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;

	for(int i=1;i<m;i++) {
		a=Get(),b=Get();
		e[a].push_back(b);
		e[b].push_back(a);
	}
	ll tot=0;
	for(rt=m;rt>=1;rt--) (tot+=work())%=mod;
	cout<<tot<<"\n";

	return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define N 2005
#define M 15

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

const ll mod=1e9+7;
const ll Mod=998244353;
int n,m;
ll f[N][M];
struct road {int to,next;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}
vector<int>e[N];
ll fac[N],ifac[N];
ll ksm(ll t,ll x) {
	ll ans=1;
	for(;x;x>>=1,t=t*t%mod)
		if(x&1) ans=ans*t%mod;
	return ans;
}

ll Hash[N];
ll Hash2[N];
const ll p=666233,p2=2017;
int size[N];
bool cmp(int a,int b) {
	if(size[a]!=size[b]) return size[a]<size[b];
	if(Hash[a]!=Hash[b]) return Hash[a]<Hash[b];
	return Hash2[a]<Hash2[b];
}

ll t[N];
vector<int>sn[N];
int dep[N];
void dfs1(int v,int fr) {
	size[v]=1;
	for(int i=0;i<e[v].size();i++) {
		int to=e[v][i];
		if(to==fr) continue ;
		sn[v].push_back(to);
		dep[to]=dep[v]+1;
		dfs1(to,v);
		size[v]+=size[to];
	}
	sort(sn[v].begin(),sn[v].end(),cmp);
	t[v]=1;
	for(int i=0;i<sn[v].size();i++) {
		int j=i;
//		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]) j++;
		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]&&Hash2[sn[v][j]]==Hash2[sn[v][j+1]]) j++;
		t[v]=t[v]*ifac[j-i+1]%mod;
		i=j;
	}
	for(int i=0;i<sn[v].size();i++) {
		Hash[v]=(Hash[v]*p+Hash[sn[v][i]])%mod;
		Hash2[v]=(Hash2[v]*p2+Hash2[sn[v][i]])%Mod;
	}
	Hash[v]=(Hash[v]*p+size[v])%mod;
	Hash2[v]=(Hash2[v]*p2+dep[v])%Mod;
}

int st[N],top;
int cal(int v,int u) {
	if(!top) return 0;
	static ll ans[1<<13],g[1<<13];
	int num=sn[u].size();
	for(int i=0;i<1<<num;i++) ans[i]=0;
	ans[0]=1;
	for(int i=1;i<=top;i++) {
		memcpy(g,ans,sizeof(g));
		int now=st[i];
		for(int j=0;j<num;j++) {
			if(!f[now][sn[u][j]]) continue ;
			int t=1<<j;
			for(int sta=0;sta<1<<num;sta++) {
				if(!(sta&t)) g[sta|t]=(g[sta|t]+ans[sta]*f[now][sn[u][j]])%mod;
			}
		}
		memcpy(ans,g,sizeof(g));
	}
	return ans[(1<<num)-1]*t[u]%mod;
}

ll ans;
int rt;
void solve(int v,int fr) {
	for(int i=1;i<=m;i++) if(sn[i].size()==0) f[v][i]=1;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		solve(to,v);
	}
	top=0;
	for(int i=h[v];i;i=s[i].next) {
		if(s[i].to==fr) continue ;
		st[++top]=s[i].to;
	}
	for(int i=1;i<=m;i++) {
		if(sn[i].size()) {
			f[v][i]=cal(v,i);
		}
	}
	(ans+=f[v][rt])%=mod;
}

#define pr pair<int,int>
#define mp(a,b) make_pair(a,b)
map<pr,int>vis;
int work() {
	for(int i=1;i<=m;i++) sn[i].clear();
	for(int i=1;i<=m;i++) Hash[i]=Hash2[i]=0;
	dep[rt]=1;
	dfs1(rt,0);
	if(vis.find(mp(Hash[rt],Hash2[rt]))!=vis.end()) return 0;
//	cout<<"rt="<<rt<<"\n";
	vis[mp(Hash[rt],Hash2[rt])]=1;
	memset(f,0,sizeof(f));
	ans=0;
	solve(1,0);
	return ans;
}

int main() {
	n=Get();
	int a,b;
	for(int i=1;i<n;i++) {
		a=Get(),b=Get();
		add(a,b),add(b,a);
	}
	m=Get();
	fac[0]=1;
	for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;
	ifac[m]=ksm(fac[m],mod-2);
	for(int i=m-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;

	for(int i=1;i<m;i++) {
		a=Get(),b=Get();
		e[a].push_back(b);
		e[b].push_back(a);
	}
	ll tot=0;
	for(rt=m;rt>=1;rt--) (tot+=work())%=mod;
	cout<<tot<<"\n";

	return 0;
}
/*
20
11 15
2 12
5 6
3 18
3 4
1 12
15 8
20 7
14 5
8 12
13 18
10 18
16 19
20 9
13 17
8 16
5 17
15 13
9 15
3
2 1
3 1
*/


#include<bits/stdc++.h>
#define ll long long
#define N 2005
#define M 15

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

const ll mod=1e9+7;
const ll Mod=998244353;

int n,m;
ll f[N][M];
struct road {int to,next;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}
vector<int>e[N];
ll fac[N],ifac[N];
ll ksm(ll t,ll x) {
	ll ans=1;
	for(;x;x>>=1,t=t*t%mod)
		if(x&1) ans=ans*t%mod;
	return ans;
}

ll Hash[N];
ll Hash2[N];
const ll p=666233,p2=134341;
unsigned ll p3=233333;

int size[N];
bool cmp(int a,int b) {
	if(size[a]!=size[b]) return size[a]<size[b];
	if(Hash[a]!=Hash[b]) return Hash[a]<Hash[b];
	return Hash2[a]<Hash2[b];
}

ll t[N];
vector<int>sn[N];
int dep[N],mxdep[N];
void dfs1(int v,int fr) {
	size[v]=1;
	mxdep[v]=dep[v];
	for(int i=0;i<e[v].size();i++) {
		int to=e[v][i];
		if(to==fr) continue ;
		sn[v].push_back(to);
		dep[to]=dep[v]+1;
		dfs1(to,v);
		mxdep[v]=max(mxdep[v],mxdep[to]);
		size[v]+=size[to];
	}
	sort(sn[v].begin(),sn[v].end(),cmp);
	t[v]=1;
	for(int i=0;i<sn[v].size();i++) {
		int j=i;
//		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]) j++;
		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]&&Hash2[sn[v][j]]==Hash2[sn[v][j+1]]) j++;
		t[v]=t[v]*ifac[j-i+1]%mod;
		i=j;
	}
	for(int i=0;i<sn[v].size();i++) {
		Hash[v]=(Hash[v]*p+Hash[sn[v][i]])%mod;
		Hash2[v]=(Hash2[v]*p2+Hash2[sn[v][i]])%Mod;
	}
	Hash[v]=(Hash[v]*p+size[v])%mod;
	Hash2[v]=(Hash2[v]*p2+mxdep[v])%Mod;
}

int st[N],top;
int cal(int v,int u) {
	if(!top) return 0;
	static ll ans[1<<13],g[1<<13];
	int num=sn[u].size();
	for(int i=0;i<1<<num;i++) ans[i]=0;
	ans[0]=1;
	for(int i=1;i<=top;i++) {
		memcpy(g,ans,sizeof(g));
		int now=st[i];
		for(int j=0;j<num;j++) {
			if(!f[now][sn[u][j]]) continue ;
			int t=1<<j;
			for(int sta=0;sta<1<<num;sta++) {
				if(!(sta&t)) g[sta|t]=(g[sta|t]+ans[sta]*f[now][sn[u][j]])%mod;
			}
		}
		memcpy(ans,g,sizeof(g));
	}
	return ans[(1<<num)-1]*t[u]%mod;
}

ll ans;
int rt;
void solve(int v,int fr) {
	for(int i=1;i<=m;i++) if(sn[i].size()==0) f[v][i]=1;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		solve(to,v);
	}
	top=0;
	for(int i=h[v];i;i=s[i].next) {
		if(s[i].to==fr) continue ;
		st[++top]=s[i].to;
	}
	for(int i=1;i<=m;i++) {
		if(sn[i].size()) {
			f[v][i]=cal(v,i);
		}
	}
	(ans+=f[v][rt])%=mod;
}

#define pr pair<int,int>
#define mp(a,b) make_pair(a,b)
map<pr,int>vis;
int work() {
	for(int i=1;i<=m;i++) sn[i].clear();
	for(int i=1;i<=m;i++) Hash[i]=Hash2[i]=0;
	dep[rt]=1;
	dfs1(rt,0);
	if(vis.find(mp(Hash[rt],Hash2[rt]))!=vis.end()) return 0;
//	cout<<"rt="<<rt<<"\n";
	vis[mp(Hash[rt],Hash2[rt])]=1;
	memset(f,0,sizeof(f));
	ans=0;
	solve(1,0);
	return ans;
}

int main() {
	n=Get();
	int a,b;
	for(int i=1;i<n;i++) {
		a=Get(),b=Get();
		add(a,b),add(b,a);
	}
	m=Get();
	fac[0]=1;
	for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;
	ifac[m]=ksm(fac[m],mod-2);
	for(int i=m-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;

	for(int i=1;i<m;i++) {
		a=Get(),b=Get();
		e[a].push_back(b);
		e[b].push_back(a);
	}
	ll tot=0;
	for(rt=m;rt>=1;rt--) (tot+=work())%=mod;
	cout<<tot<<"\n";

	return 0;
}
/*
20
11 15
2 12
5 6
3 18
3 4
1 12
15 8
20 7
14 5
8 12
13 18
10 18
16 19
20 9
13 17
8 16
5 17
15 13
9 15
3
2 1
3 1
*/


#include<bits/stdc++.h>
#define ll long long
#define N 2005
#define M 15

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

const ll mod=1e9+7;
const ll Mod=998244353;
int n,m;
ll f[N][M];
struct road {int to,next;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}
vector<int>e[N];
ll fac[N],ifac[N];
ll ksm(ll t,ll x) {
	ll ans=1;
	for(;x;x>>=1,t=t*t%mod)
		if(x&1) ans=ans*t%mod;
	return ans;
}

ll Hash[N];
ll Hash2[N];
const ll p=666233,p2=134341;
int size[N];
bool cmp(int a,int b) {
	if(size[a]!=size[b]) return size[a]<size[b];
	if(Hash[a]!=Hash[b]) return Hash[a]<Hash[b];
	return Hash2[a]<Hash2[b];
}

ll t[N];
vector<int>sn[N];
int dep[N];
void dfs1(int v,int fr) {
	size[v]=1;
	for(int i=0;i<e[v].size();i++) {
		int to=e[v][i];
		if(to==fr) continue ;
		sn[v].push_back(to);
		dep[to]=dep[v]+1;
		dfs1(to,v);
		size[v]+=size[to];
	}
	sort(sn[v].begin(),sn[v].end(),cmp);
	t[v]=1;
	for(int i=0;i<sn[v].size();i++) {
		int j=i;
//		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]) j++;
		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]&&Hash2[sn[v][j]]==Hash2[sn[v][j+1]]) j++;
		t[v]=t[v]*ifac[j-i+1]%mod;
		i=j;
	}
	for(int i=0;i<sn[v].size();i++) {
		Hash[v]=(Hash[v]*p+Hash[sn[v][i]])%mod;
		Hash2[v]=(Hash2[v]*p2+Hash2[sn[v][i]])%Mod;
	}
	Hash[v]=(Hash[v]*p+size[v])%mod;
	Hash2[v]=(Hash2[v]*p2+dep[v])%Mod;
}

int st[N],top;
int cal(int v,int u) {
	if(!top) return 0;
	static ll ans[1<<13],g[1<<13];
	int num=sn[u].size();
	for(int i=0;i<1<<num;i++) ans[i]=0;
	ans[0]=1;
	for(int i=1;i<=top;i++) {
		memcpy(g,ans,sizeof(g));
		int now=st[i];
		for(int j=0;j<num;j++) {
			if(!f[now][sn[u][j]]) continue ;
			int t=1<<j;
			for(int sta=0;sta<1<<num;sta++) {
				if(!(sta&t)) g[sta|t]=(g[sta|t]+ans[sta]*f[now][sn[u][j]])%mod;
			}
		}
		memcpy(ans,g,sizeof(g));
	}
	return ans[(1<<num)-1]*t[u]%mod;
}

ll ans;
int rt;
void solve(int v,int fr) {
	for(int i=1;i<=m;i++) if(sn[i].size()==0) f[v][i]=1;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		solve(to,v);
	}
	top=0;
	for(int i=h[v];i;i=s[i].next) {
		if(s[i].to==fr) continue ;
		st[++top]=s[i].to;
	}
	for(int i=1;i<=m;i++) {
		if(sn[i].size()) {
			f[v][i]=cal(v,i);
		}
	}
	(ans+=f[v][rt])%=mod;
}

#define pr pair<int,int>
#define mp(a,b) make_pair(a,b)
map<pr,int>vis;
int work() {
	for(int i=1;i<=m;i++) sn[i].clear();
	for(int i=1;i<=m;i++) Hash[i]=Hash2[i]=0;
	dep[rt]=1;
	dfs1(rt,0);
	if(vis.find(mp(Hash[rt],Hash2[rt]))!=vis.end()) return 0;
//	cout<<"rt="<<rt<<"\n";
	vis[mp(Hash[rt],Hash2[rt])]=1;
	memset(f,0,sizeof(f));
	ans=0;
	solve(1,0);
	return ans;
}

int main() {
	n=Get();
	int a,b;
	for(int i=1;i<n;i++) {
		a=Get(),b=Get();
		add(a,b),add(b,a);
	}
	m=Get();
	fac[0]=1;
	for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;
	ifac[m]=ksm(fac[m],mod-2);
	for(int i=m-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;

	for(int i=1;i<m;i++) {
		a=Get(),b=Get();
		e[a].push_back(b);
		e[b].push_back(a);
	}
	ll tot=0;
	for(rt=m;rt>=1;rt--) (tot+=work())%=mod;
	cout<<tot<<"\n";

	return 0;
}
/*
20
11 15
2 12
5 6
3 18
3 4
1 12
15 8
20 7
14 5
8 12
13 18
10 18
16 19
20 9
13 17
8 16
5 17
15 13
9 15
3
2 1
3 1
*/


#include<bits/stdc++.h>
#define ll long long
#define N 2005
#define M 15

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

const ll mod=1e9+7;
const ll Mod=998244353;

int n,m;
ll f[N][M];
struct road {int to,next;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}
vector<int>e[N];
ll fac[N],ifac[N];
ll ksm(ll t,ll x) {
	ll ans=1;
	for(;x;x>>=1,t=t*t%mod)
		if(x&1) ans=ans*t%mod;
	return ans;
}

ll Hash[N];
ll Hash2[N];
const ll p=666233,p2=134341;
unsigned ll p3=233333;

int size[N];
bool cmp(int a,int b) {
	if(size[a]!=size[b]) return size[a]<size[b];
	if(Hash[a]!=Hash[b]) return Hash[a]<Hash[b];
	return Hash2[a]<Hash2[b];
}

ll t[N];
vector<int>sn[N];
int dep[N],mxdep[N];
void dfs1(int v,int fr) {
	size[v]=1;
	mxdep[v]=dep[v];
	for(int i=0;i<e[v].size();i++) {
		int to=e[v][i];
		if(to==fr) continue ;
		sn[v].push_back(to);
		dep[to]=dep[v]+1;
		dfs1(to,v);
		mxdep[v]=max(mxdep[v],mxdep[to]);
		size[v]+=size[to];
	}
	sort(sn[v].begin(),sn[v].end(),cmp);
	t[v]=1;
	for(int i=0;i<sn[v].size();i++) {
		int j=i;
		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]&&Hash2[sn[v][j]]==Hash2[sn[v][j+1]]) j++;
		t[v]=t[v]*ifac[j-i+1]%mod;
		i=j;
	}
	Hash2[v]=Hash[v]='(';
	ll now=1,now2=1;
	for(int i=0;i<sn[v].size();i++) {
		Hash[v]=((Hash[v]*now%mod)^Hash[sn[v][i]])%mod;
		Hash2[v]=((Hash2[v]*now2%Mod)^Hash2[sn[v][i]])%Mod;
		now=now*p%mod;
		now2=now2*p2%Mod;
	}
	Hash[v]=(Hash[v]*p+')')%mod;
	Hash2[v]=(Hash2[v]*p+')')%Mod;
}

int st[N],top;
int cal(int v,int u) {
	if(!top) return 0;
	static ll ans[1<<13],g[1<<13];
	int num=sn[u].size();
	for(int i=0;i<1<<num;i++) ans[i]=0;
	ans[0]=1;
	for(int i=1;i<=top;i++) {
		memcpy(g,ans,sizeof(g));
		int now=st[i];
		for(int j=0;j<num;j++) {
			if(!f[now][sn[u][j]]) continue ;
			int t=1<<j;
			for(int sta=0;sta<1<<num;sta++) {
				if(!(sta&t)) g[sta|t]=(g[sta|t]+ans[sta]*f[now][sn[u][j]])%mod;
			}
		}
		memcpy(ans,g,sizeof(g));
	}
	return ans[(1<<num)-1]*t[u]%mod;
}

ll ans;
int rt;
void solve(int v,int fr) {
	for(int i=1;i<=m;i++) if(sn[i].size()==0) f[v][i]=1;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		solve(to,v);
	}
	top=0;
	for(int i=h[v];i;i=s[i].next) {
		if(s[i].to==fr) continue ;
		st[++top]=s[i].to;
	}
	for(int i=1;i<=m;i++) {
		if(sn[i].size()) {
			f[v][i]=cal(v,i);
		}
	}
	(ans+=f[v][rt])%=mod;
}

#define pr pair<int,int>
#define mp(a,b) make_pair(a,b)
map<pr,int>vis;
int work() {
	for(int i=1;i<=m;i++) sn[i].clear();
	for(int i=1;i<=m;i++) Hash[i]=Hash2[i]=0;
	dep[rt]=1;
	dfs1(rt,0);
	if(vis.find(mp(Hash[rt],Hash2[rt]))!=vis.end()) return 0;
	vis[mp(Hash[rt],Hash2[rt])]=1;
	memset(f,0,sizeof(f));
	ans=0;
	solve(1,0);
	return ans;
}

int main() {
	n=Get();
	int a,b;
	for(int i=1;i<n;i++) {
		a=Get(),b=Get();
		add(a,b),add(b,a);
	}
	m=Get();
	fac[0]=1;
	for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;
	ifac[m]=ksm(fac[m],mod-2);
	for(int i=m-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;

	for(int i=1;i<m;i++) {
		a=Get(),b=Get();
		e[a].push_back(b);
		e[b].push_back(a);
	}
	ll tot=0;
	for(rt=m;rt>=1;rt--) (tot+=work())%=mod;
	cout<<tot<<"\n";

	return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define N 2005
#define M 15

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

const ll mod=1e9+7;
const ll Mod=1e9+7;
int n,m;
ll f[N][M];
struct road {int to,next;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}
vector<int>e[N];
ll fac[N],ifac[N];
ll ksm(ll t,ll x) {
	ll ans=1;
	for(;x;x>>=1,t=t*t%mod)
		if(x&1) ans=ans*t%mod;
	return ans;
}

ll Hash[N];
ll Hash2[N];
const ll p=171,p2=2017;
int size[N];
bool cmp(int a,int b) {
	if(size[a]!=size[b]) return size[a]<size[b];
	return Hash[a]<Hash[b];
}

ll t[N];
vector<int>sn[N];
void dfs1(int v,int fr) {
	size[v]=1;
	for(int i=0;i<e[v].size();i++) {
		int to=e[v][i];
		if(to==fr) continue ;
		sn[v].push_back(to);
		dfs1(to,v);
		size[v]+=size[to];
	}
	sort(sn[v].begin(),sn[v].end(),cmp);
	t[v]=1;
	for(int i=0;i<sn[v].size();i++) {
		int j=i;
//		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]) j++;
		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]&&Hash2[sn[v][j]]==Hash2[sn[v][j+1]]) j++;
		t[v]=t[v]*ifac[j-i+1]%mod;
		i=j;
	}
	for(int i=0;i<sn[v].size();i++) {
		Hash[v]=(Hash[v]*p+Hash[sn[v][i]])%mod;
		Hash2[v]=(Hash2[v]*p2+Hash2[sn[v][i]])%Mod;
	}
	Hash[v]=(Hash[v]*p+size[v]+sn[v].size())%mod;
	Hash2[v]=(Hash2[v]*p2+size[v]+sn[v].size())%Mod;
}

int st[N],top;
int cal(int v,int u) {
	if(!top) return 0;
	static ll ans[1<<13],g[1<<13];
	int num=sn[u].size();
	for(int i=0;i<1<<num;i++) ans[i]=0;
	ans[0]=1;
	for(int i=1;i<=top;i++) {
		memcpy(g,ans,sizeof(g));
		int now=st[i];
		for(int j=0;j<num;j++) {
			if(!f[now][sn[u][j]]) continue ;
			int t=1<<j;
			for(int sta=0;sta<1<<num;sta++) {
				if(!(sta&t)) g[sta|t]=(g[sta|t]+ans[sta]*f[now][sn[u][j]])%mod;
			}
		}
		memcpy(ans,g,sizeof(g));
	}
	return ans[(1<<num)-1]*t[u]%mod;
}

ll ans;
int rt;
void solve(int v,int fr) {
	for(int i=1;i<=m;i++) if(sn[i].size()==0) f[v][i]=1;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		solve(to,v);
	}
	top=0;
	for(int i=h[v];i;i=s[i].next) {
		if(s[i].to==fr) continue ;
		st[++top]=s[i].to;
	}
	for(int i=1;i<=m;i++) {
		if(sn[i].size()) {
			f[v][i]=cal(v,i);
		}
	}
	(ans+=f[v][rt])%=mod;
}

map<int,int>vis;
int work() {
	for(int i=1;i<=m;i++) sn[i].clear();
	for(int i=1;i<=m;i++) Hash[i]=Hash2[i]=0;
	dfs1(rt,0);
	if(vis.find(Hash[rt])!=vis.end()) return 0;
//	cout<<"rt="<<rt<<"\n";
	vis[Hash[rt]]=1;
	memset(f,0,sizeof(f));
	ans=0;
	solve(1,0);
	return ans;
}

int main() {
	n=Get();
	int a,b;
	for(int i=1;i<n;i++) {
		a=Get(),b=Get();
		add(a,b),add(b,a);
	}
	m=Get();
	fac[0]=1;
	for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;
	ifac[m]=ksm(fac[m],mod-2);
	for(int i=m-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;

	for(int i=1;i<m;i++) {
		a=Get(),b=Get();
		if(n==807) {
			cout<<a<<" "<<b<<"\n";
		}
		e[a].push_back(b);
		e[b].push_back(a);
	}
	ll tot=0;
	for(rt=m;rt>=1;rt--) (tot+=work())%=mod;
	cout<<tot<<"\n";

	return 0;
}
/*
2
1 2
12
12 9
4 2
11 9
7 4
11 3
10 6
2 8
2 12
1 2
4 5
9 10
*/


#include<bits/stdc++.h>
#define ll long long
#define N 2005
#define M 15

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

const ll mod=1e9+7;
const ll Mod=998244353;

int n,m;
ll f[N][M];
struct road {int to,next;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}
vector<int>e[N];
ll fac[N],ifac[N];
ll ksm(ll t,ll x) {
	ll ans=1;
	for(;x;x>>=1,t=t*t%mod)
		if(x&1) ans=ans*t%mod;
	return ans;
}

ll Hash[N];
ll Hash2[N];
const ll p=666233,p2=134341;
unsigned ll p3=233333;

int size[N];
bool cmp(int a,int b) {
	if(size[a]!=size[b]) return size[a]<size[b];
	if(Hash[a]!=Hash[b]) return Hash[a]<Hash[b];
	return Hash2[a]<Hash2[b];
}

ll t[N];
vector<int>sn[N];
int dep[N],mxdep[N];
void dfs1(int v,int fr) {
	size[v]=1;
	mxdep[v]=dep[v];
	for(int i=0;i<e[v].size();i++) {
		int to=e[v][i];
		if(to==fr) continue ;
		sn[v].push_back(to);
		dep[to]=dep[v]+1;
		dfs1(to,v);
		mxdep[v]=max(mxdep[v],mxdep[to]);
		size[v]+=size[to];
	}
	sort(sn[v].begin(),sn[v].end(),cmp);
	t[v]=1;
	for(int i=0;i<sn[v].size();i++) {
		int j=i;
//		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]) j++;
		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]&&Hash2[sn[v][j]]==Hash2[sn[v][j+1]]) j++;
		t[v]=t[v]*ifac[j-i+1]%mod;
		i=j;
	}
	Hash2[v]=Hash[v]='(';
	for(int i=0;i<sn[v].size();i++) {
		Hash[v]=(Hash[v]*p+Hash[sn[v][i]])%mod;
		Hash2[v]=(Hash2[v]*p2+Hash2[sn[v][i]])%Mod;
	}
	Hash[v]=(Hash[v]*p+')')%mod;
	Hash2[v]=(Hash2[v]*p+')')%Mod;

}

int st[N],top;
int cal(int v,int u) {
	if(!top) return 0;
	static ll ans[1<<13],g[1<<13];
	int num=sn[u].size();
	for(int i=0;i<1<<num;i++) ans[i]=0;
	ans[0]=1;
	for(int i=1;i<=top;i++) {
		memcpy(g,ans,sizeof(g));
		int now=st[i];
		for(int j=0;j<num;j++) {
			if(!f[now][sn[u][j]]) continue ;
			int t=1<<j;
			for(int sta=0;sta<1<<num;sta++) {
				if(!(sta&t)) g[sta|t]=(g[sta|t]+ans[sta]*f[now][sn[u][j]])%mod;
			}
		}
		memcpy(ans,g,sizeof(g));
	}
	return ans[(1<<num)-1]*t[u]%mod;
}

ll ans;
int rt;
void solve(int v,int fr) {
	for(int i=1;i<=m;i++) if(sn[i].size()==0) f[v][i]=1;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		solve(to,v);
	}
	top=0;
	for(int i=h[v];i;i=s[i].next) {
		if(s[i].to==fr) continue ;
		st[++top]=s[i].to;
	}
	for(int i=1;i<=m;i++) {
		if(sn[i].size()) {
			f[v][i]=cal(v,i);
		}
	}
	(ans+=f[v][rt])%=mod;
}

#define pr pair<int,int>
#define mp(a,b) make_pair(a,b)
map<pr,int>vis;
int work() {
	for(int i=1;i<=m;i++) sn[i].clear();
	for(int i=1;i<=m;i++) Hash[i]=Hash2[i]=0;
	dep[rt]=1;
	dfs1(rt,0);
	if(vis.find(mp(Hash[rt],Hash2[rt]))!=vis.end()) return 0;
//	cout<<"rt="<<rt<<"\n";
	vis[mp(Hash[rt],Hash2[rt])]=1;
	memset(f,0,sizeof(f));
	ans=0;
	solve(1,0);
	return ans;
}

int main() {
	n=Get();
	int a,b;
	for(int i=1;i<n;i++) {
		a=Get(),b=Get();
		add(a,b),add(b,a);
	}
	m=Get();
	fac[0]=1;
	for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;
	ifac[m]=ksm(fac[m],mod-2);
	for(int i=m-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;

	for(int i=1;i<m;i++) {
		a=Get(),b=Get();
		e[a].push_back(b);
		e[b].push_back(a);
	}
	ll tot=0;
	for(rt=m;rt>=1;rt--) (tot+=work())%=mod;
	cout<<tot<<"\n";

	return 0;
}
/*
20
11 15
2 12
5 6
3 18
3 4
1 12
15 8
20 7
14 5
8 12
13 18
10 18
16 19
20 9
13 17
8 16
5 17
15 13
9 15
3
2 1
3 1
*/


#include<bits/stdc++.h>
#define ll long long
#define N 2005
#define M 15

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

const ll mod=1e9+7;
int n,m;
ll f[N][M];
struct road {int to,next;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}
vector<int>e[N];
ll fac[N],ifac[N];
ll ksm(ll t,ll x) {
	ll ans=1;
	for(;x;x>>=1,t=t*t%mod)
		if(x&1) ans=ans*t%mod;
	return ans;
}

ll Hash[N];
const ll p=233;
int size[N];
bool cmp(int a,int b) {
	if(size[a]!=size[b]) return size[a]<size[b];
	return Hash[a]<Hash[b];
}

ll t[N];
vector<int>sn[N];
void dfs1(int v,int fr) {
	size[v]=1;
	for(int i=0;i<e[v].size();i++) {
		int to=e[v][i];
		if(to==fr) continue ;
		sn[v].push_back(to);
		dfs1(to,v);
		size[v]+=size[to];
	}
	sort(sn[v].begin(),sn[v].end(),cmp);
	t[v]=1;
	for(int i=0;i<sn[v].size();i++) {
		int j=i;
		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]) j++;
		t[v]=t[v]*ifac[j-i+1]%mod;
		i=j;
	}
	for(int i=0;i<sn[v].size();i++) Hash[v]=(Hash[v]*p+Hash[sn[v][i]])%mod;
	Hash[v]=(Hash[v]*p+size[v])%mod;
}

int Mod(int a) {return a<mod?a:a-mod;}
int st[N],top;
int cal(int v,int u) {
	if(!top) return 0;
	static ll ans[1<<13],g[1<<13];
	int num=sn[u].size();
	for(int i=0;i<1<<num;i++) ans[i]=0;
	ans[0]=1;
	for(int i=1;i<=top;i++) {
		memcpy(g,ans,sizeof(g));
		int now=st[i];
		for(int j=0;j<num;j++) {
			if(!f[now][sn[u][j]]) continue ;
			int t=1<<j;
			for(int sta=0;sta<1<<num;sta++) {
				if(!(sta&t)) g[sta|t]=(g[sta|t]+ans[sta]*f[now][sn[u][j]])%mod;
			}
		}
		memcpy(ans,g,sizeof(g));
	}
	return ans[(1<<num)-1]*t[u]%mod;
}

ll ans;
int rt;
void solve(int v,int fr) {
	for(int i=1;i<=m;i++) if(sn[i].size()==0) f[v][i]=1;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		solve(to,v);
	}
	top=0;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		st[++top]=to;
	}
	for(int i=1;i<=m;i++) {
		if(sn[i].size()) {
			f[v][i]=cal(v,i);
		}
	}
	(ans+=f[v][rt])%=mod;
}

map<int,int>vis;
int work() {
	for(int i=1;i<=m;i++) sn[i].clear();
	memset(Hash,0,sizeof(Hash));
	dfs1(rt,0);
	if(vis.find(Hash[rt])!=vis.end()) return 0;
	vis[Hash[rt]]=1;
	memset(f,0,sizeof(f));
	ans=0;
	solve(1,0);
	return ans;
}

int main() {
	n=Get();
	int a,b;
	for(int i=1;i<n;i++) {
		a=Get(),b=Get();
		add(a,b),add(b,a);
	}
	m=Get();
	fac[0]=1;
	for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;
	ifac[m]=ksm(fac[m],mod-2);
	for(int i=m-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;

	for(int i=1;i<m;i++) {
		a=Get(),b=Get();
		e[a].push_back(b);
		e[b].push_back(a);
	}
	ll tot=0;
	for(rt=m;rt>=1;rt--) (tot+=work())%=mod;
	cout<<tot<<"\n";

	return 0;
}


#include<bits/stdc++.h>
#define ll long long
#define N 2005
#define M 15

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

const ll mod=1e9+7;
const ll Mod=998244353;
int n,m;
ll f[N][M];
struct road {int to,next;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}
vector<int>e[N];
ll fac[N],ifac[N];
ll ksm(ll t,ll x) {
	ll ans=1;
	for(;x;x>>=1,t=t*t%mod)
		if(x&1) ans=ans*t%mod;
	return ans;
}

ll Hash[N];
ll Hash2[N];
const ll p=171,p2=2017;
int size[N];
bool cmp(int a,int b) {
	if(size[a]!=size[b]) return size[a]<size[b];
	return Hash[a]<Hash[b];
}

ll t[N];
vector<int>sn[N];
void dfs1(int v,int fr) {
	size[v]=1;
	for(int i=0;i<e[v].size();i++) {
		int to=e[v][i];
		if(to==fr) continue ;
		sn[v].push_back(to);
		dfs1(to,v);
		size[v]+=size[to];
	}
	sort(sn[v].begin(),sn[v].end(),cmp);
	t[v]=1;
	for(int i=0;i<sn[v].size();i++) {
		int j=i;
//		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]) j++;
		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]&&Hash2[sn[v][j]]==Hash2[sn[v][j+1]]) j++;
		t[v]=t[v]*ifac[j-i+1]%mod;
		i=j;
	}
	for(int i=0;i<sn[v].size();i++) {
		Hash[v]=(Hash[v]*p+Hash[sn[v][i]])%mod;
		Hash2[v]=(Hash2[v]*p2+Hash2[sn[v][i]])%Mod;
	}
	Hash[v]=(Hash[v]*p+1)%mod;
	Hash2[v]=(Hash2[v]*p2+1)%Mod;
}

int st[N],top;
int cal(int v,int u) {
	if(!top) return 0;
	static ll ans[1<<13],g[1<<13];
	int num=sn[u].size();
	for(int i=0;i<1<<num;i++) ans[i]=0;
	ans[0]=1;
	for(int i=1;i<=top;i++) {
		memcpy(g,ans,sizeof(g));
		int now=st[i];
		for(int j=0;j<num;j++) {
			if(!f[now][sn[u][j]]) continue ;
			int t=1<<j;
			for(int sta=0;sta<1<<num;sta++) {
				if(!(sta&t)) g[sta|t]=(g[sta|t]+ans[sta]*f[now][sn[u][j]])%mod;
			}
		}
		memcpy(ans,g,sizeof(g));
	}
	return ans[(1<<num)-1]*t[u]%mod;
}

ll ans;
int rt;
void solve(int v,int fr) {
	for(int i=1;i<=m;i++) if(sn[i].size()==0) f[v][i]=1;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		solve(to,v);
	}
	top=0;
	for(int i=h[v];i;i=s[i].next) {
		if(s[i].to==fr) continue ;
		st[++top]=s[i].to;
	}
	for(int i=1;i<=m;i++) {
		if(sn[i].size()) {
			f[v][i]=cal(v,i);
		}
	}
	(ans+=f[v][rt])%=mod;
}

map<int,int>vis;
int work() {
	for(int i=1;i<=m;i++) sn[i].clear();
	for(int i=1;i<=m;i++) Hash[i]=Hash2[i]=0;
	dfs1(rt,0);
	if(vis.find(Hash[rt])!=vis.end()) return 0;
//	cout<<"rt="<<rt<<"\n";
	vis[Hash[rt]]=1;
	memset(f,0,sizeof(f));
	ans=0;
	solve(1,0);
	return ans;
}

int main() {
	n=Get();
	int a,b;
	for(int i=1;i<n;i++) {
		a=Get(),b=Get();
		add(a,b),add(b,a);
	}
	m=Get();
	fac[0]=1;
	for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;
	ifac[m]=ksm(fac[m],mod-2);
	for(int i=m-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;

	for(int i=1;i<m;i++) {
		a=Get(),b=Get();
		e[a].push_back(b);
		e[b].push_back(a);
	}
	ll tot=0;
	for(rt=m;rt>=1;rt--) (tot+=work())%=mod;
	cout<<tot<<"\n";

	return 0;
}
/*
2
1 2
12
12 9
4 2
11 9
7 4
11 3
10 6
2 8
2 12
1 2
4 5
9 10
*/


#include<bits/stdc++.h>
#define ll long long
#define N 2005
#define M 15

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

const ll mod=1e9+7;
const ll Mod=1e9+7;
int n,m;
ll f[N][M];
struct road {int to,next;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}
vector<int>e[N];
ll fac[N],ifac[N];
ll ksm(ll t,ll x) {
	ll ans=1;
	for(;x;x>>=1,t=t*t%mod)
		if(x&1) ans=ans*t%mod;
	return ans;
}

ll Hash[N];
ll Hash2[N];
const ll p=171,p2=2017;
int size[N];
bool cmp(int a,int b) {
	if(size[a]!=size[b]) return size[a]<size[b];
	return Hash[a]<Hash[b];
}

ll t[N];
vector<int>sn[N];
void dfs1(int v,int fr) {
	size[v]=1;
	for(int i=0;i<e[v].size();i++) {
		int to=e[v][i];
		if(to==fr) continue ;
		sn[v].push_back(to);
		dfs1(to,v);
		size[v]+=size[to];
	}
	sort(sn[v].begin(),sn[v].end(),cmp);
	t[v]=1;
	for(int i=0;i<sn[v].size();i++) {
		int j=i;
//		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]) j++;
		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]&&Hash2[sn[v][j]]==Hash2[sn[v][j+1]]) j++;
		t[v]=t[v]*ifac[j-i+1]%mod;
		i=j;
	}
	for(int i=0;i<sn[v].size();i++) {
		Hash[v]=(Hash[v]*p+Hash[sn[v][i]])%mod;
		Hash2[v]=(Hash2[v]*p2+Hash2[sn[v][i]])%Mod;
	}
	Hash[v]=(Hash[v]*p+size[v]+sn[v].size())%mod;
	Hash2[v]=(Hash2[v]*p2+size[v]+sn[v].size())%Mod;
}

int st[N],top;
int cal(int v,int u) {
	if(!top) return 0;
	static ll ans[1<<13],g[1<<13];
	int num=sn[u].size();
	for(int i=0;i<1<<num;i++) ans[i]=0;
	ans[0]=1;
	for(int i=1;i<=top;i++) {
		memcpy(g,ans,sizeof(g));
		int now=st[i];
		for(int j=0;j<num;j++) {
			if(!f[now][sn[u][j]]) continue ;
			int t=1<<j;
			for(int sta=0;sta<1<<num;sta++) {
				if(!(sta&t)) g[sta|t]=(g[sta|t]+ans[sta]*f[now][sn[u][j]])%mod;
			}
		}
		memcpy(ans,g,sizeof(g));
	}
	return ans[(1<<num)-1]*t[u]%mod;
}

ll ans;
int rt;
void solve(int v,int fr) {
	for(int i=1;i<=m;i++) if(sn[i].size()==0) f[v][i]=1;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		solve(to,v);
	}
	top=0;
	for(int i=h[v];i;i=s[i].next) {
		if(s[i].to==fr) continue ;
		st[++top]=s[i].to;
	}
	for(int i=1;i<=m;i++) {
		if(sn[i].size()) {
			f[v][i]=cal(v,i);
		}
	}
	(ans+=f[v][rt])%=mod;
}

map<int,int>vis;
int work() {
	for(int i=1;i<=m;i++) sn[i].clear();
	for(int i=1;i<=m;i++) Hash[i]=Hash2[i]=0;
	dfs1(rt,0);
	if(vis.find(Hash[rt])!=vis.end()) return 0;
//	cout<<"rt="<<rt<<"\n";
	vis[Hash[rt]]=1;
	memset(f,0,sizeof(f));
	ans=0;
	solve(1,0);
	return ans;
}

int main() {
	n=Get();
	int a,b;
	for(int i=1;i<n;i++) {
		a=Get(),b=Get();
		add(a,b),add(b,a);
	}
	m=Get();
	fac[0]=1;
	for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;
	ifac[m]=ksm(fac[m],mod-2);
	for(int i=m-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;

	for(int i=1;i<m;i++) {
		a=Get(),b=Get();
		e[a].push_back(b);
		e[b].push_back(a);
	}
	ll tot=0;
	for(rt=m;rt>=1;rt--) (tot+=work())%=mod;
	cout<<tot<<"\n";

	return 0;
}
/*
2
1 2
12
12 9
4 2
11 9
7 4
11 3
10 6
2 8
2 12
1 2
4 5
9 10
*/


#include<bits/stdc++.h>
#define ll long long
#define N 2005
#define M 15

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

const ll mod=1e9+7;
int n,m;
ll f[N][M];
struct road {int to,next;}s[N<<1];
int h[N],cnt;
void add(int i,int j) {s[++cnt]=(road) {j,h[i]};h[i]=cnt;}
vector<int>e[N];
ll fac[N],ifac[N];
ll ksm(ll t,ll x) {
	ll ans=1;
	for(;x;x>>=1,t=t*t%mod)
		if(x&1) ans=ans*t%mod;
	return ans;
}

ll Hash[N];
const ll p=2017;
int size[N];
bool cmp(int a,int b) {
	if(size[a]!=size[b]) return size[a]<size[b];
	return Hash[a]<Hash[b];
}

ll t[N];
vector<int>sn[N];
void dfs1(int v,int fr) {
	size[v]=1;
	for(int i=0;i<e[v].size();i++) {
		int to=e[v][i];
		if(to==fr) continue ;
		sn[v].push_back(to);
		dfs1(to,v);
		size[v]+=size[to];
	}
	sort(sn[v].begin(),sn[v].end(),cmp);
	t[v]=1;
	for(int i=0;i<sn[v].size();i++) {
		int j=i;
		while(j+1<sn[v].size()&&size[sn[v][i]]==size[sn[v][j+1]]&&Hash[sn[v][i]]==Hash[sn[v][j+1]]) j++;
		t[v]=t[v]*ifac[j-i+1]%mod;
		i=j;
	}
	for(int i=0;i<sn[v].size();i++) Hash[v]=(Hash[v]*p+Hash[sn[v][i]])%mod;
	Hash[v]=(Hash[v]*p+size[v])%mod;
}

int Mod(int a) {return a<mod?a:a-mod;}
int st[N],top;
int cal(int v,int u) {
	if(!top) return 0;
	static ll ans[1<<13],g[1<<13];
	int num=sn[u].size();
	for(int i=0;i<1<<num;i++) ans[i]=0;
	ans[0]=1;
	for(int i=1;i<=top;i++) {
		memcpy(g,ans,sizeof(g));
		int now=st[i];
		for(int j=0;j<num;j++) {
			if(!f[now][sn[u][j]]) continue ;
			int t=1<<j;
			for(int sta=0;sta<1<<num;sta++) {
				if(!(sta&t)) g[sta|t]=(g[sta|t]+ans[sta]*f[now][sn[u][j]])%mod;
			}
		}
		memcpy(ans,g,sizeof(g));
	}
	return ans[(1<<num)-1]*t[u]%mod;
}

ll ans;
int rt;
void solve(int v,int fr) {
	for(int i=1;i<=m;i++) if(sn[i].size()==0) f[v][i]=1;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		solve(to,v);
	}
	top=0;
	for(int i=h[v];i;i=s[i].next) {
		int to=s[i].to;
		if(to==fr) continue ;
		st[++top]=to;
	}
	for(int i=1;i<=m;i++) {
		if(sn[i].size()) {
			f[v][i]=cal(v,i);
		}
	}
	(ans+=f[v][rt])%=mod;
}

map<int,int>vis;
int work() {
	for(int i=1;i<=m;i++) sn[i].clear();
	memset(Hash,0,sizeof(Hash));
	dfs1(rt,0);
	if(vis.find(Hash[rt])!=vis.end()) return 0;
	vis[Hash[rt]]=1;
	memset(f,0,sizeof(f));
	ans=0;
	solve(1,0);
	return ans;
}

int main() {
	n=Get();
	int a,b;
	for(int i=1;i<n;i++) {
		a=Get(),b=Get();
		add(a,b),add(b,a);
	}
	m=Get();
	fac[0]=1;
	for(int i=1;i<=m;i++) fac[i]=fac[i-1]*i%mod;
	ifac[m]=ksm(fac[m],mod-2);
	for(int i=m-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;

	for(int i=1;i<m;i++) {
		a=Get(),b=Get();
		if(n==807) {
			cout<<a<<" "<<b<<"\n";
		}
		e[a].push_back(b);
		e[b].push_back(a);
	}
	ll tot=0;
	for(rt=m;rt>=1;rt--) (tot+=work())%=mod;
	cout<<tot<<"\n";

	return 0;
}


/// by ztx
/// blog.csdn.net/hzoi_ztx
/// learnt from myy  (matthew99:http://codeforces.com/contest/762/submission/24128833)

#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i< (r);i++)
#define r(x)   read(x)
typedef long long ll ;
int CH , NEG ;
template <typename TP>inline void read(TP& ret) {
    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
    if (CH == '-') NEG = true , CH = getchar() ;
    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
    if (NEG) ret = -ret ;
}
using namespace std;
#define  kN   1000LL
#define  kM   12LL
#define  pb   push_back
#define  kMod 1000000007LL

int n, m, ANS;
int now[(1<<kM)+5], nxt[(1<<kM)+5];
vector<int> G[kN+5], g[kM+5];
map<int,vector<int> > STA;
map<int,int> ans[kN+5];

inline int blen(int x) { return 32 - __builtin_clz(x); } // __builtin_clz()   count leading zeros
inline int combine(int x, int y) { return x << blen(y) | y; }

inline void P(int x) {
    for (int i = 30; ~i; i -- ) { printf("%d",int(bool(x&(1<<i)))); } puts("");
}

int dfs0(int u,int fa = 0) {
    int h = 1;
    vector<int> H;
    for (auto v : g[u]) if (v != fa) H.pb(dfs0(v,u));
    sort(H.begin(), H.end());
    // minimum representation of tree
    for (auto s : H) h = combine(h,s);
    h <<= 1;
//printf("h[%d] = ",u);
//P(h);
    if (!STA.count(h)) STA[h] = H;
    return h;
}

void dfs(int u,int fa = 0) {
    vector<int> chd;
    for (auto v : G[u]) if (v != fa) chd.pb(v), dfs(v,u);
    for (const auto &sta : STA) {
        auto &H = sta.second;
        int h = sta.first, N = H.size();
        memset(now, 0, sizeof(int)*(1<<N));
        now[0] = 1;
        for (auto ch : chd) {
            memcpy(nxt, now, sizeof(int)*(1<<N));
            for (int i = 0; i < N; i ++ ) {
                int num = ans[ch][H[i]];
                if (!num) continue;
                for (int j = (1<<N)-1; j >= 0; j -- )
                    if (now[j] && !(j>>i & 1) && !(i && H[i]==H[i-1] && !(j>>(i-1) & 1)))
                        (nxt[j|(1<<i)] += (ll)now[j]*num%kMod) %= kMod;
            }
            memcpy(now, nxt, sizeof(int)*(1<<N));
        }
        if (now[(1 << N) - 1]) {
            ans[u][h] = now[(1 << N) - 1];
            if (blen(h) == (m<<1)) (ANS += now[(1<<N)-1]) %= kMod;
        }
    }
}

int main() {
    int i, u, v;
    r(n);
    rep (i,1,n)
        r(u), r(v), G[u].pb(v), G[v].pb(u);
    r(m);
    rep (i,1,m)
        r(u), r(v), g[u].pb(v), g[v].pb(u);
    Rep (i,1,m) dfs0(i);
    dfs(1);
    (ANS += kMod) %= kMod;
    printf("%d\n", ANS);
    END: getchar(), getchar();
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int N = 1020 , M = 15;
const int Mod = 1000000007;
int n,m,t1,t2,Head1[N],Head2[N];
int g[1<<M],p[1<<M],ans;
map < int , vector<int> > List;
map < int , int > f[N];
struct edge { int ver,next; } e1[N*2],e2[N*2];
inline void insert(int x,int y,int id)
{
    if ( id == 1 )
        e1[++t1] = (edge){y,Head1[x]} , Head1[x] = t1,
        e1[++t1] = (edge){x,Head1[y]} , Head1[y] = t1;
    if ( id == 2 )
        e2[++t2] = (edge){y,Head2[x]} , Head2[x] = t2,
        e2[++t2] = (edge){x,Head2[y]} , Head2[y] = t2;
}
inline int read(void)
{
    int x = 0 , w = 0; char ch = ' ';
    while ( !isdigit(ch) ) w |= ch=='-' , ch = getchar();
    while ( isdigit(ch) ) x = x*10 + ch-48 , ch = getchar();
    return w ? -x : x;
}
inline void input(void)
{
    n = read();
    for (int i=1;i<n;i++)
        insert( read() , read() , 1 );
    m = read();
    for (int i=1;i<m;i++)
        insert( read() , read() , 2 );
}
inline int lenth(int x) { return 32 - __builtin_clz(x); }
inline void connect(int &x,int y) { x = x << lenth(y) | y; }
inline int Ergodic(int x,int fa)
{
    int S = 1;
    vector < int > cur;
    for (int i=Head2[x];i;i=e2[i].next)
    {
        int y = e2[i].ver;
        if ( y == fa ) continue;
        cur.push_back( Ergodic( y , x ) );
    }
    sort( cur.begin() , cur.end() );
    vector < int > :: iterator it;
    for (it=cur.begin();it!=cur.end();it++)
        connect( S , *it );
    S <<= 1;
    if ( !List.count( S ) ) List[S] = cur;
    return S;
}
inline void dp(int x,int fa)
{
    vector < int > ch;
    for (int i=Head1[x];i;i=e1[i].next)
    {
        int y = e1[i].ver;
        if ( y == fa ) continue;
        ch.push_back( y ) , dp( y , x );
    }
    map < int , vector< int > > :: iterator it;
    for (it=List.begin();it!=List.end();it++)
    {
        vector < int > cur = it -> second;
        int S = it -> first , len = cur.size();
        memset( g , 0 , sizeof g );
        g[0] = 1;
        for (int i=0;i<ch.size();i++)
        {
            memcpy( p , g , sizeof g );
            for (int j=0;j<len;j++)
            {
                int val = f[ch[i]][cur[j]];
                if ( val == 0 ) continue;
                for (int k=(1<<len)-1;k>=0;k--)
                    if ( g[k] && !( k >> j & 1 ) && ( j == 0 || cur[j] != cur[j-1] || ( k >> (j-1) & 1 ) ) )
                        p[k|(1<<j)] = ( p[k|(1<<j)] + 1LL * g[k] * val % Mod ) % Mod;
            }
            memcpy( g , p , sizeof p );
        }
        if ( g[(1<<len)-1] )
        {
            f[x][S] = g[(1<<len)-1];
            if ( lenth(S) == (m<<1) )
                ans = ( ans + f[x][S] ) % Mod;
        }
    }
}
int main(void)
{
    input();
    for (int i=1;i<=m;i++)
        Ergodic( i , 0 );
    dp( 1 , 0 );
    printf("%d\n",ans);
    return 0;
}


/// by ztx
/// blog.csdn.net/hzoi_ztx
/// learnt from myy  (matthew99:http://codeforces.com/contest/762/submission/24128833)
#include <bits/stdc++.h>
#define Rep(i,l,r) for(i=(l);i<=(r);i++)
#define rep(i,l,r) for(i=(l);i< (r);i++)
#define r(x)   read(x)
typedef long long ll ;
int CH , NEG ;
template <typename TP>inline void read(TP& ret) {
    ret = NEG = 0 ; while (CH=getchar() , CH<'!') ;
    if (CH == '-') NEG = true , CH = getchar() ;
    while (ret = ret*10+CH-'0' , CH=getchar() , CH>'!') ;
    if (NEG) ret = -ret ;
}
using namespace std;
#define  kN   1000LL
#define  kM   12LL
#define  pb   push_back
#define  kMod 1000000007LL

int n, m, ANS;
int now[(1<<kM)+5], nxt[(1<<kM)+5];
vector<int> G[kN+5], g[kM+5];
map<int,vector<int> > STA;
map<int,int> ans[kN+5];

inline int blen(int x) { return 32 - __builtin_clz(x); } // __builtin_clz()   count leading zeros
inline int combine(int x, int y) { return x << blen(y) | y; }

inline void P(int x) {
    for (int i = 30; ~i; i -- ) { printf("%d",int(bool(x&(1<<i)))); } puts("");
}

int dfs0(int u,int fa = 0) {
    int h = 1;
    vector<int> H;
    for (auto v : g[u]) if (v != fa) H.pb(dfs0(v,u));
    sort(H.begin(), H.end());
    // minimum representation of tree
    for (auto s : H) h = combine(h,s);
    h <<= 1;
//printf("h[%d] = ",u);
//P(h);
    if (!STA.count(h)) STA[h] = H;
    return h;
}

void dfs(int u,int fa = 0) {
    vector<int> chd;
    for (auto v : G[u]) if (v != fa) chd.pb(v), dfs(v,u);
    for (const auto &sta : STA) {
        auto &H = sta.second;
        int h = sta.first, N = H.size();
        memset(now, 0, sizeof(int)*(1<<N));
        now[0] = 1;
        for (auto ch : chd) {
            memcpy(nxt, now, sizeof(int)*(1<<N));
            for (int i = 0; i < N; i ++ ) {
                int num = ans[ch][H[i]];
                if (!num) continue;
                for (int j = (1<<N)-1; j >= 0; j -- )
                    if (now[j] && !(j>>i & 1) && !(i && H[i]==H[i-1] && !(j>>(i-1) & 1)))
                        (nxt[j|(1<<i)] += (ll)now[j]*num%kMod) %= kMod;
            }
            memcpy(now, nxt, sizeof(int)*(1<<N));
        }
        if (now[(1 << N) - 1]) {
            ans[u][h] = now[(1 << N) - 1];
            if (blen(h) == (m<<1)) (ANS += now[(1<<N)-1]) %= kMod;
        }
    }
}

int main() {
    int i, u, v;
    r(n);
    rep (i,1,n)
        r(u), r(v), G[u].pb(v), G[v].pb(u);
    r(m);
    rep (i,1,m)
        r(u), r(v), g[u].pb(v), g[v].pb(u);
    Rep (i,1,m) dfs0(i);
    dfs(1);
    (ANS += kMod) %= kMod;
    printf("%d\n", ANS);
    return 0;
}