CSES - Shared codeLink to this code: https://cses.fi/paste/76b082b9448a13798977a8/
#include <bits/stdc++.h>
using namespace std;

#define ar array
#define ascii_lowercase "abcdefghijklmnopqrstuvwxyz"
#define ascii_uppercase "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define int long long
#define ll long long
#define inf 0x3f3f3f3f3f3f3f3f
#define yes "yes"
#define no "no"
#define mod 1000000007
#define endl '\n'
#define add insert
using vec2D = vector<vector<int>>;
using vec1D = vector<int>;


#define fo(i, a, b) for (int i = a; i < b; ++i)
#define ro(i, a, b) for (int i = a; i >b; --i)

// #define fo(i, a, b, ...) for (int i = a; i < b; i+=(__VA_ARGS__ == NULL ? 1 : __VA_ARGS__))
// #define ro(i, a, b, ...) for (int i = a; i > b; i-=(__VA_ARGS__ == NULL ? 1 : __VA_ARGS__))

#define all(x) (x).begin(),(x).end()
#define rall(x) (x).rbegin(),(x).rend()
#define len(x) (int)(x.size())
#define fi first
#define se second
#define append push_back
// #define tuple make_pair

#define gh(x) {cout << (x) << '\n';}
// #define Outd(x) {printf("%.10f",x);cout<<endl;}
#define print_vec(vec) { for (size_t iii = 0; iii < vec.size(); iii++) { if (iii == vec.size() - 1) std::cout << vec[iii] << '\n'; else std::cout << vec[iii] << ' '; } }


template<class... T> void in(T&... x) {(cin >> ... >> x);}
#define integer(...) int __VA_ARGS__; in(__VA_ARGS__);cin.ignore();
#ifndef ONLINE_JUDGE
#define de(var) {cerr << #var << ": "; debug_view(var);}
template<typename T> inline void debug_view(T e){cerr << e << endl;}
template<typename T> inline void debug_view(pair<T,T> p){cerr << p.first << ' ' << p.second << endl;}
template<typename T> inline void debug_view(queue<T> q){while(!q.empty()) {cerr << q.front() << " "; q.pop();}cerr << endl;}
template<typename T> inline void debug_view(deque<T> q){for(auto i:q) {cerr << i << " ";}cerr << endl;}
template<typename T> inline void debug_view(set<T> s){for(auto x:s){cerr << x << ' ';}cerr << endl;}
template<typename T> inline void debug_view(multiset<T> s){for(auto x:s){cerr << x << ' ';}cerr << endl;}
template<typename T> inline void debug_view(vector<pair<T,T>> &v){for(auto [a,b]: v){cerr<<"{"<<a<<" "<<b<<"} ";} cerr << endl;}
template<typename T> inline void debug_view(vector<T> &v){for(auto e: v){cerr << e << " ";} cerr << endl;}
template<typename T> inline void debug_view(vector<vector<pair<T,T>>> &vv){cerr << "----" << endl;for(auto &v: vv){debug_view(v);} cerr << "--------" << endl;}
template<typename T> inline void debug_view(vector<vector<T>> &vv){cerr << "----" << endl;for(auto &v: vv){debug_view(v);} cerr << "--------" << endl;}
// template<typename T> inline void debug_view(vector<ar> &vv){cerr << "----" << endl;for(auto &v: vv){debug_view(v);} cerr << "--------" << endl;}
template<typename T1,typename T2> inline void debug_view(map<T1,T2> &mp){cerr << "----" << endl;for(auto [k,v]: mp){cerr << k << ' ' << v << endl;} cerr << "--------" << endl;}
template<typename T1,typename T2> inline void debug_view(unordered_map<T1,T2> &mp){cerr << "----" << endl;for(auto [k,v]: mp){cerr << k << ' ' << v << endl;} cerr << "--------" << endl;}
template<typename T1,typename T2> inline void debug_view(map<T1,vector<T2>> &mp){cerr<<"----"<<endl;for(auto [k,v]: mp){cerr<<k<<": ";debug_view(v);} cerr << "--------" << endl;}
template<typename T1,typename T2,typename T3> inline void debug_view(map<pair<T1,T2>,T3> &mp){cerr << "----" << endl;for(auto [p,v]: mp){cerr<<'{'<<p.first<<' '<<p.second<<'}'<<": "<<v<<endl;} cerr<<"--------"<<endl;}
#define deb(var) {cerr << #var << ": "; debugb_view(var);}
template<typename T> inline void debugb_view(T e){bitset<20> b(e); cerr<<b<<endl;}
template<typename T> inline void debugb_view(vector<T> &v){cerr<<"----"<<endl;for(auto e: v){debugb_view(e);}}
#else
#define de(var) {}
#endif

mt19937_64 RNG(chrono::steady_clock::now().time_since_epoch().count());


template<typename T>
unordered_map<T, int> Counter(const vector<T>& a) {
    unordered_map<T, int> counts;
    for (const T& x : a) {
        counts[x]++;
    }
    return counts;
}

vector<int> lst() {
    
    string input;
    getline(cin, input);
    stringstream ss(input);
    vector<int> result;
    int num;
    while (ss >> num) {
        result.push_back(num);
    }
    
    return result;
}

// int integer() {
//     int num;
//     cin >> num;
//     cin.ignore();
//     return num;
// }

string st() {
    string s;
    getline(cin, s);
    if (!s.empty() && s[s.length()-1] == '\n') {
        s.erase(s.length()-1);
    }
    return s;
}

vector<vector<int>> matrixNum(int m) {
    vector<vector<int>> result;
    for (int i = 0; i < m; ++i) {
        result.push_back(lst());
    }
    return result;
}

vector<string> matrixStr(int m) {
    vector<string> matrix;
    for (int i = 0; i < m; i++) {
        matrix.push_back(st());
    }
    return matrix;
}


bool h(int i, int j, string& s, vector<vector<char>>& sp) {
    int r = sp.size();
    int c = sp[0].size();
    for (char d : s) {
        if (d == 'U') {
            i--;
        } else if (d == 'R') {
            j++;
        } else if (d == 'D') {
            i++;
        } else if (d == 'L') {
            j--;
        }
        if (i >= 0 && i < r && j >= 0 && j < c) {
            if (sp[i][j] == '#') {
                return false;
            }
        } else {
            return false;
        }
    }
    return sp[i][j] == '.';
}

template<typename T>
typename T::value_type sum(const T& container) {
    return std::accumulate(container.begin(), container.end(), typename T::value_type());
}


ll max(ll a, ll b) {
    if (a > b)
        return a;
    else
        return b;
}
ll min(ll a, ll b) {
    if (a < b)
        return a;
    else
        return b;
}
int gcd(int a, int b) {
    if (a == 0)
        return b;
    return gcd(b % a, a);
}
int findGCD(vector<int>& arr, int n) {
    int result = arr[0];
    for (int i = 1; i < n; i++) {
        result = gcd(arr[i], result);
 
        if (result == 1) {
            return 1;
        }
    }
    return result;
}
// int power(int x, unsigned int y, unsigned int M) {
//     if (y == 0)
//         return 1;
 
//     int p = power(x, y / 2, M) % M;
//     p = (p * p) % M;
 
//     return (y % 2 == 0) ? p : (x * p) % M;
// }

int power(int base, unsigned int exponent, unsigned int modulus) {   //int power(int base, int exponent, int modulus) { 
    int result = 1;
    base = base % modulus;

    while (exponent > 0) {
        if (exponent % 2 == 1) {
            result = (result * base) % modulus;
        }

        exponent = exponent >> 1;
        base = (base * base) % modulus;
    }

    return result;
}

int modInverse(int A, int M)  // returns modular inverse (works when M is prime)
{
    int g = gcd(A, M);
    if (g != 1) {  // inverse doesnt exist
        return 0;
    }
    else {
        // If a and m are relatively prime, then modulo
        // inverse is a^(m-2) mod m
        return power(A, M - 2, M);
    }
}

bool isPrime(int n)  // O(rt(n))
{
    // Corner cases
    if (n <= 1)
        return false;
    if (n<4)
        return true;
    if (n%2==0 || n%3==0 || n%5==0)
        return false;
    // suppose n=7 that is prime and its pair are (1,7)
    // so if a no. is prime then it can be check by numbers smaller than square root
    //  of the n
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0)
            return false;
    }
    return true;
}

struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
};

vector<int> myprimes;
unordered_set<int,custom_hash> myprimess;
void SieveOfEratosthenes(int n) {
    // Create a boolean array "prime[0..n]" and initialize
    // all entries it as true. A value in prime[i] will
    // finally be false if i is Not a prime, else true.
    vector<bool> prime(n + 1, true);
 
    for (int p = 2; p * p <= n; p++) {
        // If prime[p] is not changed, then it is a prime
        if (prime[p] == true) {
            // Update all multiples of p greater than or
            // equal to the square of it numbers which are
            // multiple of p and are less than p^2 are
            // already been marked.
            for (int i = p * p; i <= n; i += p)
                prime[i] = false;
        }
    }
 
    // Print all prime numbers
    for (int p = 2; p <= n; p++)
        if (prime[p]) {
            myprimes.push_back(p);
            myprimess.insert(p);
        }
}
void primeFactors(int n) {
    for (int i = 2; i * i <= n; i++) {
        if (n % i == 0) myprimes.push_back(i);
        while (n % i == 0) n /= i;
    }
    if (n > 1) myprimes.push_back(n);
}



class DSU {
    private:
        vector<int> p,rank,setSize;
        int numSets;
    public:
        DSU(int n) {
            n++;
            p.assign(n,0);
            for (int i = 0; i < n; i++) {
                p[i] = i;
            }
            rank.assign(n,0); // height of all trees are 0.
            setSize.assign(n,1); // size of individual sets are 1
            numSets = n-1;
        }
 
        int find(int x) {
            if (p[x]==x) return x;
            return p[x] = find(p[x]); // path compression
        }
 
        bool same(int x, int y) {return find(x)==find(y);}
 
        bool unionn(int i, int j) {
            // if (same(i,j)) return false;
            int x = find(i);
            int y = find(j);
            if (x==y) return true;

            if (rank[x]>rank[y]) swap(x,y);
            p[x] = y;
            if (rank[x]==rank[y]) rank[y]++;
            setSize[y] += setSize[x];
            numSets--;
            
            return false;
        }
 
        int size(int x) {
            return setSize[x];
        }
 
        int numDisjointSets() {
            return numSets;
        }
        
};

// bool cmp(const vector<int>& a,const vector<int>& b) {
//     return a[1]<b[1];
    
// }

// bool cmp(pair<int,int> &a, pair<int,int> &b)
// {
//     return a.second < b.second;
// }

// #include <ext/pb_ds/assoc_container.hpp>
// #include <ext/pb_ds/tree_policy.hpp>
// using namespace __gnu_pbds;

// template <typename T>
// using ordered_set = tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

vector<vector<int>> d4 = {{1,0},{0,1},{-1,0},{0,-1}};
vector<vector<int>> d8 = {{0,1},{1,0},{0,-1},{-1,0},{1,-1},{-1,1},{1,1},{-1,-1}};
unordered_map<char,vector<int>> dir={
    {'U', {-1, 0}},
    {'R', {0, 1}},
    {'D', {1, 0}},
    {'L', {0, -1}}
};

vector<int> djisktra(int src, const vector<vector<pair<int, int>>>& d, int n) {
    vector<int> p(n + 1, inf);
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> a;
    a.push({0, src});
    p[src] = 0;

    while (!a.empty()) {
        auto [di, node] = a.top();
        a.pop();
        if (p[node]<di) continue;
        
        for (auto [j, weight] : d[node]) {
            if (di+ weight < p[j]) {
                p[j] = di + weight;
                a.push({p[j], j});
            }
        }
    }

    return p;
}


// int vis[1001][1001];

// vector<int> parent[1001][1001];
// char dd[1001][1001];

// int dp[100005][2],vis[100005];

// 0x3f
// const int mxn = 2e5+5;
// int n,m, coins[mxn],par[mxn],dp[mxn],maxi;
// vector<int> adj[mxn],adj2[mxn],adj3[mxn];
// vector<int> stk;

// bool vis[mxn];

template<typename T>
void dea(const T &a, int l, int r) {
    for (int i = l; i < r; ++i) {
        cerr << a[i] << " ";
    }
    cerr << endl;
}



void precompute(){
 
    
 
}

const int mxN = 2*(1e5)+4;
// const int maxm = 5500;
 
int n,q, dp[18][mxN], depth[mxN],res[mxN];
vector<int> adj[mxN];
// int a[mxN];

    
   
 
void dfs(int u, int par){

    
    for (auto v:adj[u]){
        if (v==par)continue;
        dp[0][v] = u;
        depth[v] = max(depth[v],1+depth[u]);
        dfs(v,u);
            
    }
    
}




void dfs2(int u, int par){
    for (auto v:adj[u]){
        if (v==par)continue;
        dfs2(v,u);
        res[u] += res[v];
            
    }

}
 
 
void solve()
{
    cin>>n>>q;
    memset(dp,-1,sizeof(dp));
    fo(i,0,n-1){
        integer(u,v);
        u--;v--;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    dfs(0,-1);
    fo(i,1,18){
        fo(j,0,n){
            if (dp[i-1][j]==-1){
                dp[i][j] = -1;continue;
            }
            dp[i][j] = dp[i-1][dp[i-1][j]];
        }
    }

    
    // int res[n];


    while (q--){
        integer(a,b);
        a--;b--;
        if (depth[a]>depth[b]){
            swap(a,b);
        }
        res[a]++;
        res[b]++;
        int dif = depth[b]-depth[a];
        int b1 = b;
        int a1 = a;
        // int x = b;
        fo(i,0,18)
        {
            if (dif&(1<<i)){

                b1 = dp[i][b1];
                if (b1==-1)
                    break;
            }
        }
        int lca;
        if (a1==b1){
            lca = a1;
            
        }else{
            fo(i,0,18){
                if (dp[i][a1]==dp[i][b1]){
                    break;
                }
                a1 = dp[i][a1];
                b1 = dp[i][b1];
            }
            lca = dp[0][a1];
        }
        res[lca]-=1;
        if (dp[0][lca]!=-1){
            lca = dp[0][lca];
            res[lca]-=1;
        }
        // dea(res,0,n);
        
    }

    dfs2(0,-1);
    fo(i,0,n){
        cout<<res[i]<<" ";
    }
    

    // gh(res);
}

int32_t main() {

    auto begin = std::chrono::high_resolution_clock::now();
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    #ifndef ONLINE_JUDGE
    freopen("in.txt","r",stdin);
    freopen("out.txt","w",stdout);
    #endif

    int t = 1;
    // integer(t);
    precompute();

    while (t--)
    {
        solve();
    }
    auto end = std::chrono::high_resolution_clock::now();
    auto elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end - begin);
    cerr << "Time measured: " << elapsed.count() * 1e-9 << " seconds.\n"; 

    return 0;
}