树形DP+LCA
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100100
using namespace std;
int head1[N],head2[N],cnt,num;
int dp[N],f[N];
bool flag[N];
struct Edge{
int v,next;
}edge[N*4];
void addedge(int u,int v,int *head){
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].v=u;
edge[cnt].next=head[v];
head[v]=cnt++;
}
void init(){
memset(head1,-1,sizeof(head1));
memset(head2,-1,sizeof(head2));
memset(flag,0,sizeof(flag));
memset(dp,0,sizeof(dp));
cnt=num=0;
}
int find(int u){
if(f[u]==u)return u;
return f[u]=find(f[u]);
}
void tarjan(int u,int fa){
int i;
f[u]=u;
for(i=head1[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v!=fa){
tarjan(v,u);
f[v]=u;
}
}
flag[u]=1;
for(i=head2[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(flag[v]){
int t=find(v);
dp[u]++,dp[v]++,dp[t]-=2;
}
}
}
void DP(int u,int fa){
int i;
for(i=head1[u];i!=-1;i=edge[i].next){
int v=edge[i].v;
if(v!=fa){
DP(v,u);
dp[u]+=dp[v];
}
}
}
int main(){
int i,n,m;
int u,v;
scanf("%d %d",&n,&m);
init();
for(i=1;i<n;i++){
scanf("%d %d",&u,&v);
addedge(u,v,head1);
}
for(i=1;i<=m;i++){
scanf("%d %d",&u,&v);
addedge(u,v,head2);
}
tarjan(1,0);
DP(1,0);
int ans=0;
for(i=2;i<=n;i++){
if(dp[i]==0)ans+=m;
else if(dp[i]==1)ans++;
}
printf("%d\n",ans);
return 0;
}