#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=0,f=1;char c=Getchar();
for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
return x*f;
}
typedef long long ll;
const int maxn=100010;
int n,m,e,first[maxn],next[maxn<<1],to[maxn<<1];
void AddEdge(int u,int v) {
to[++e]=v;next[e]=first[u];first[u]=e;
to[++e]=u;next[e]=first[v];first[v]=e;
}
int anc[maxn][20],dep[maxn],st[maxn],en[maxn],ToT;
void dfs(int x,int fa) {
anc[x][0]=fa;rep(i,1,19) anc[x][i]=anc[anc[x][i-1]][i-1];
dep[x]=dep[fa]+1;st[x]=++ToT;
ren if(to[i]!=fa) dfs(to[i],x);
en[x]=ToT;
}
int swim(int x,int k) {
rep(i,0,19) if(k>>i&1) x=anc[x][i];
return x;
}
struct Rect {
int x,l,r,val;
bool operator < (const Rect& ths) const {return x<ths.x;}
}A[maxn<<2];
struct Point {
int x,y;
bool operator < (const Point& ths) const {return x<ths.x||(x==ths.x&&y<ths.y);}
}B[maxn];
int N,M;
void AddRect(int x,int y,int l,int r) {
if(x>y||l>r) return;
if(x<l) swap(x,l),swap(y,r);
A[++N]=(Rect){x,l,r,1};A[++N]=(Rect){y+1,l,r,-1};
}
void AddPoint(int x,int y) {
if(x<y) swap(x,y);
B[++M]=(Point){x,y};
}
int sumv[maxn];
int query(int x) {int res=0;for(;x;x-=x&-x) res+=sumv[x];return res;}
void add(int x,int v) {for(;x<=n;x+=x&-x) sumv[x]+=v;}
ll ans;
ll gcd(ll a,ll b) {return !b?a:gcd(b,a%b);}
int main() {
n=read();m=read();
rep(i,2,n) AddEdge(read(),read());
dfs(1,0);
rep(i,1,m) {
int u=read(),v=read();AddPoint(st[u],st[v]);
if(dep[u]<dep[v]) swap(u,v);
if(u==v) AddRect(st[u],en[u],1,st[u]),AddRect(st[u],en[u],en[u]+1,n);
else if(st[u]>=st[v]&&st[u]<=en[v]) {
v=swim(u,dep[u]-dep[v]-1);
AddRect(st[u],en[u],1,st[v]-1);
AddRect(st[u],en[u],en[v]+1,n);
}
else AddRect(st[u],en[u],st[v],en[v]);
}
sort(A+1,A+N+1);sort(B+1,B+M+1);int j=1;
rep(i,1,M) {
while(j<=N&&A[j].x<=B[i].x) add(A[j].l,A[j].val),add(A[j].r+1,-A[j].val),j++;
ans+=query(B[i].y);
}
rep(i,1,M) {
int j=i;
while(j<=M&&B[j].x==B[i].x&&B[j].y==B[i].y) j++;j--;
ans-=(ll)(j-i+1)*(j-i)/2;
i=j;
}
ans-=m;ll ans2=(ll)m*(m-1)/2,c=gcd(ans,ans2);
printf("%lld/%lld\n",ans/c,ans2/c);
return 0;
}