/*from: https://blog.csdn.net/tmeteorj/article/details/9915247*/
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3005,M=40005;
int ar[N];
inline int lowbit(int x){
return x&-x;
}
int sum(int i){
int s=0;
for(;i>0;s+=ar[i],i-=lowbit(i));
return s;
}
void add(int i){
for(;i<N;ar[i]+=1,i+=lowbit(i));
}
int check(int l,int r){
if(l>r)return 0;
return sum(r)-sum(l-1);
}
struct Edge{
int to,nxt;
};
struct Graph{
int head[N],nc;
Edge edge[M*2];
void Init(){
memset(head,-1,sizeof(head));
nc=0;
}
void Add(int a,int b){
edge[nc].to=b;edge[nc].nxt=head[a];head[a]=nc++;
}
void AddTwo(int a,int b){
edge[nc].to=b;edge[nc].nxt=head[a];head[a]=nc++;
edge[nc].to=a;edge[nc].nxt=head[b];head[b]=nc++;
}
}T,G;
struct STK_Heavy{//now,fa,e,dep
int now,fa,e,dep;
STK_Heavy(){}
STK_Heavy(int _n,int _f,int _e,int _d){
now=_n,fa=_f,e=_e,dep=_d;
}
}Hstk[N*2];
struct STK_Create{//now,ac,e
int now,ac,e;
STK_Create(){}
STK_Create(int _n,int _a,int _e){
now=_n,ac=_a,e=_e;
}
}Cstk[N*2];
int dep[N],anc[N],pa[N],tid[N],heavy[N],size[N],ID,n,m;
bool mark[N];
void DFS_Heavy(int root){
int top=0;
memset(mark,false,sizeof(mark));
Hstk[top]=STK_Heavy(root,-1,T.head[root],0);
while(top>=0){
STK_Heavy elem=Hstk[top];
if(!mark[elem.now]){
mark[elem.now]=true;
size[elem.now]=1;
heavy[elem.now]=-1;
pa[elem.now]=elem.fa;
dep[elem.now]=elem.dep;
}
if(elem.e==-1){
if(top){
size[elem.fa]+=size[elem.now];
if(heavy[elem.fa]==-1||size[heavy[elem.fa]]<size[elem.now]){
heavy[elem.fa]=elem.now;
}
}
top--;
continue;
}
int to=T.edge[elem.e].to;
Hstk[top].e=T.edge[elem.e].nxt;
if(mark[to])continue;
Hstk[++top]=STK_Heavy(to,elem.now,T.head[to],elem.dep+1);
}
}
void DFS_Create(int root){
int top=0;
Cstk[0]=STK_Create(root,root,T.head[root]);
memset(mark,false,sizeof(mark));
while(top>=0){
STK_Create elem=Cstk[top];
if(!mark[elem.now]){
mark[elem.now]=true;
tid[elem.now]=++ID;
anc[elem.now]=elem.ac;
if(heavy[elem.now]!=-1){
Cstk[++top]=STK_Create(heavy[elem.now],elem.ac,T.head[heavy[elem.now]]);
continue;
}
}
if(elem.e==-1){
top--;
continue;
}
int to=T.edge[elem.e].to;
Cstk[top].e=T.edge[elem.e].nxt;
if(mark[to])continue;
Cstk[++top]=STK_Create(to,to,T.head[to]);
}
}
bool Query(int f,int s){
while(anc[f]!=anc[s]){
int fs=anc[s];
if(check(tid[fs],tid[s])!=0)return true;
s=pa[fs];
}
if(f==s)return false;
else if(check(tid[f]+1,tid[s])!=0)return true;
else return false;
}
void Set(int f,int s){
int p;
while(anc[f]!=anc[s]){
s=pa[p=anc[s]];
}
if(s==f){
add(tid[p]);
}
else{
add(tid[f]+1);
}
}
void Tree_Chain(){
memset(ar,0,sizeof(ar));
ID=0;
DFS_Heavy(1);
DFS_Create(1);
}
int ans;
void dfs(int now){
mark[now]=true;
for(int i=T.head[now];i!=-1;i=T.edge[i].nxt){
int to=T.edge[i].to;
if(mark[to])continue;
dfs(to);
}
for(int i=G.head[now];i!=-1;i=G.edge[i].nxt){
int to=G.edge[i].to;
if(!Query(now,to)){
Set(now,to);
ans++;
}
}
}
int main(){
int a,b;
while(scanf("%d%d",&n,&m)!=EOF){
if(n==0&&m==0)break;
T.Init();
G.Init();
for(int i=1;i<=n-1;i++){
scanf("%d%d",&a,&b);
T.AddTwo(a,b);
}
Tree_Chain();
for(int i=n;i<=m;i++){
scanf("%d%d",&a,&b);
if(dep[a]>dep[b])swap(a,b);
G.Add(a,b);
}
memset(mark,false,sizeof(mark));
ans=0;
dfs(1);
printf("%d\n",ans);
}
return 0;
}