#include <bits/stdc++.h>
using namespace std;
#define TR(i,v)         for(__typeof((v).begin())i=(v).begin();i!=(v).end();++i)
#define DEBUG(x)        cout << #x << " = "; cout << x << endl;
#define SIZE(p)         (int)(p).size()
#define MP(a, b)        make_pair((a), (b))
#define ALL(p)          (p).begin(), (p).end()
#define rep(i, n)       for(int (i)=0; (i)<(int)(n); ++(i))
#define REP(i, a, n)    for(int (i)=(a); (i)<(int)(n); ++(i))
#define FOR(i, a, b)    for(int (i)=(int)(a); (i)<=(int)(b); ++(i))
#define FORD(i, b, a)   for(int (i)=(int)(b); (i)>=(int)(a); --(i))
#define CLR(x, y)       memset((x), (y), sizeof((x)))
typedef long long LL;
typedef long long ll;
typedef pair<int, int> pii;
char buf;
inline char xchar() { while (buf = getchar(), isspace(buf)); return buf; }
inline int xint() { while (buf = getchar(), buf < '0' || buf > '9'); int x = buf - '0'; for (; buf = getchar(), buf >= '0' && buf <= '9'; x = x * 10 + buf - '0'); return x; }
inline ll xll() { while (buf = getchar(), buf < '0' || buf > '9'); ll x = buf - '0'; for (; buf = getchar(), buf >= '0' && buf <= '9'; x = x * 10 + buf - '0'); return x; }
inline string xstring() { while (buf = getchar(), buf == ' ' || buf == '\n'); string x = ""; for (x += buf; buf = getchar(), buf != ' ' && buf != '\n' && buf != '\r'; x += buf); return x; }
inline string xline() { while (buf = getchar(), buf == ' ' || buf == '\n'); string x = ""; for (x += buf; buf = getchar(), buf != '\n' && buf != '\r'; x += buf); return x; }
int C1[100005], C2[100005];
LL C[200005];
struct Tree {
    vector<int> g[100005];
    int n;
    int s,t,dia;
    int dis1[100005], dis2[100005], p[100005];
    void init(int n) {
        this->n=n;
        rep(i,n)    g[i].clear();
    }
    void addedge(int u,int v) {
        g[u].push_back(v), g[v].push_back(u);
    }
    void dfs(int u,int f,int dis[]) {
        rep(i,SIZE(g[u])) {
            int v=g[u][i];
            if(v!=f) {
                dis[v]=dis[u]+1;
                dfs(v,u,dis);
            }
        }
    }
    void build() {
        dis1[0]=0;
        dfs(0,0,dis1);
        s=0;
        rep(i,n) if(dis1[i]>dis1[s])    s=i;   
        dis2[s]=0;
        dfs(s,s,dis2);
        t=0;
        rep(i,n) if(dis2[i]>dis2[t])    t=i;    
        dis1[t]=0;
        dfs(t,t,dis1);
        dia=dis1[s];
        rep(i,n)    p[i]=max(dis1[i], dis2[i]);
    }
    int mindis,maxdis;
    int gao(int C[]) {
        mindis=0x3f3f3f3f, maxdis=0;
        rep(i,n) {
            mindis=min(mindis,p[i]);
            maxdis=max(maxdis,p[i]);
        }
        rep(i,n+5)    C[i]=0;
        rep(i,n)      ++C[p[i]];
    }    
}t1,t2;
int main(int argc, char const *argv[]) {
#ifndef ONLINE_JUDGE
    freopen("J.in", "r", stdin);
    //freopen("out", "w", stdout);
#endif
    // ios::sync_with_stdio(false);		cin.tie(0);
    int n,m;
    while(scanf("%d%d", &n,&m) == 2) {
        t1.init(n), t2.init(m);
        rep(i,n-1) {
            int u,v;    u=xint(),v=xint();   --u,--v;
            t1.addedge(u,v);
        }
        rep(i,m-1) {
            int u,v;    u=xint(),v=xint();   --u,--v;
            t2.addedge(u,v);
        }
        t1.build(), t2.build();        
        double res=0;    
        int *d1=t1.p, *d2=t2.p, dia=max(t1.dia,t2.dia);
        sort(d2,d2+m);
        static int postsum[40005];  postsum[m]=0;
        FORD(i,m-1,0)   postsum[i]=d2[i]+postsum[i+1];
        rep(i,n) {
            int *f=lower_bound(d2,d2+m,dia-(d1[i]+1));
            int cnt=(int)(d2+m-f);
            res+=(LL)(d1[i]+1)*(LL)cnt + (postsum[(int)(f-d2)]);
            if(f!=d2) {
                cnt=m-cnt;
                res+=(LL)dia*cnt;
            }
        }
        res/=(double)n, res/=(double)m;
        printf("%.3f\n", res);
    }
    return 0;
}
