#ifndef LOCAL
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#endif


#include <iostream>
#include <vector>
#include <cstdio>
#include <algorithm>
#include <set>
#include <map>
#include <cassert>
#include <numeric>
#include <string>
#include <cstring>
#include <cmath>
using namespace std;

#ifdef LOCAL
	#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
	#define eprintf(...) 42
#endif

typedef long long int int64;

const int N = 2005;
const int BLOCK = 64;
const int BLM = BLOCK - 1;
const int SZ = N / BLOCK + 1;


int nei[N];
int nsz;

struct BS
{
    unsigned long long a[SZ];

    BS() : a() {}

    void doXor(int pos)
    {
        a[pos / BLOCK] ^= (1ULL << (pos & BLM));
    }

    unsigned long long get(int pos)
    {
        return (a[pos / BLOCK] >> (pos & BLM));
    }

    void operator |= (const BS &A)
    {
        for (int i = 0; i < SZ; i++)
            a[i] |= A.a[i];
    }
    void operator &= (const BS &A)
    {
        for (int i = 0; i < SZ; i++)
            a[i] &= A.a[i];
    }
    void operator *= (const BS &A) // & not
    {
        for (int i = 0; i < SZ; i++)
            a[i] &= ~A.a[i];
    }
    void operator ^= (const BS &A)
    {
        for (int i = 0; i < SZ; i++)
            a[i] ^= A.a[i];
    }

    void copyFrom(const BS &A)
    {
        for (int i = 0; i < SZ; i++)
            a[i] = A.a[i];
    }

    void getNei() const
    {
        for (int i = 0; i < SZ; i++)
        {
            if (a[i] == 0) continue;
            
            for (int h = 0; h < 8; h++)
            {
                if (((a[i] >> (h * 8)) & 255) == 0)
                    continue;
                for (int j = 8 * h; j < 8 * h + 8; j++)
                    if ((a[i] >> j) & 1ULL)
                        nei[nsz++] = i * BLOCK + j;
            }
        }
    }

    void clear()
    {
        memset(a, 0, sizeof a);
    }
};


vector <int> t[N];
BS g[N];

BS good[N * N / 2];

int pairId(int x, int y)
{
    if (x == y) throw;
    if (x < y) swap(x, y);
    return x * (x + 1) / 2 + y;
}

BS cur;
BS subTree[N];

void dfsSubtree(int v, int par)
{
    subTree[v].clear();
    subTree[v].doXor(v);
    for (int to : t[v])
    {
        if (to == par) continue;
        dfsSubtree(to, v);
        subTree[v] ^= subTree[to];
    }
}

void dfsCalc(int v, int par, int root)
{
    if (v != root)
        good[pairId(v, root)].copyFrom(cur);
    for (int to : t[v])
    {
        if (to == par) continue;
        if (v != root)
        {
            cur ^= subTree[v];
            cur.doXor(v);
            cur ^= subTree[to];
        }
        dfsCalc(to, v, root);
        if (v != root)
            cur.copyFrom(good[pairId(v, root)]);
    }
}


int main(int,  char **)
{
#ifdef LOCAL
	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);
#endif

    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 0; i < n - 1; i++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        a--;
        b--;
        t[a].push_back(b);
        t[b].push_back(a);
    }
    for (int i = 0; i < m; i++)
    {
        int a, b;
        scanf("%d%d", &a, &b);
        a--;
        b--;
        g[a].doXor(b);
        g[b].doXor(a);
    }

    for (int i = 0; i < n; i++)
    {
        cur.clear();
        dfsSubtree(i, i);
        cur.copyFrom(subTree[i]);
        dfsCalc(i, i, i);
    }

    vector <pair <int, int>> qu;

    for (int i = 0; i < n; i++)
    {
        nsz = 0;
        g[i].getNei();
        for (int j = 0; j < nsz; j++)
            qu.emplace_back(i, nei[j]);
    }

    for (int it = 0; it < (int) qu.size(); it++)
    {
        int a = qu[it].first, b = qu[it].second;
        if (g[b].get(a) == 0)
        {
            g[b].doXor(a);
            qu.emplace_back(b, a);
        }

        cur.copyFrom(good[pairId(a, b)]);
        cur &= g[b];
        cur *= g[a];

        nsz = 0;
        cur.getNei();
        for (int i = 0; i < nsz; i++)
        {
            int v = nei[i];
            if (v == a) continue;
            g[a].doXor(v);
            g[v].doXor(a);
            qu.emplace_back(a, v);
            qu.emplace_back(v, a);
        }
    }
    
    printf("%d\n", (int) qu.size() / 2);

	return 0;
}




Measured memory_bytes: 538984