#include <bits/stdc++.h>
using namespace std; 

#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define FOR(i, a, b) for( int i = a; i < (b); i++ )
#define bug(x) cout << #x << " " << x << endl;

using pii = pair<int, int>; 
using vi = vector<int>;
using ll = long long;

const int maxn = 1e5 + 10; 
const int logn = 20; 

vi adj[maxn]; 
int tin[maxn], tout[maxn], depth[maxn], pai[maxn][logn];
int dfs_time = -1;

void dfs( int u, int p ){
    pai[u][0] = p; 
    FOR(i, 1, logn) pai[u][i] = pai[pai[u][i - 1]][i - 1];

    tin[u] = ++dfs_time; 
    for( int v : adj[u] ) if( v != p ){
        depth[v] = depth[u] + 1; 
        dfs( v, u ); 
    }
    tout[u] = dfs_time; 
}

bool upper( int a, int b ){
    return tin[a] <= tin[b] && tout[b] <= tout[a]; 
}

int LCA( int a, int b ){
    if( upper( a, b ) ) return a; 
    if( upper( b, a ) ) return b; 

    for( int i = logn - 1; i >= 0; i-- ) if( !upper( pai[a][i], b ) ) a = pai[a][i]; 
    return pai[a][0];
}

int dist( int a, int b ){
    return depth[a] + depth[b] - 2*depth[LCA( a, b )];
}

struct Path{
    int a, b, lca, length; 
    Path( int x, int y ) : a(x), b(y), lca(LCA(x, y)), length(dist(x, y)) {
        if( tin[a] > tin[b] ) swap( a, b ); 
    }

    bool inter( int x ){
        return upper( lca, x ) && ( upper( x, a ) || upper( x, b ) ); 
    }

    bool disjoint( Path p ){
        return !inter(p.lca) && !p.inter(lca);
    }

    bool contains( Path p ){
        return inter(p.a) && inter(p.b) && inter(p.lca);
    }

    bool is_laminar( Path p ){
        return contains(p) || p.contains(*this) || disjoint(p);
    }

    bool operator < ( const Path &p ) const{
        if( depth[lca] != depth[p.lca] ) return depth[lca] > depth[p.lca]; 
        if( lca != p.lca ) return lca < p.lca; 
        return length < p.length;
    }
};

struct Segtree{
    struct Node{
        int x, lz; 
        Node( int x = 0 ) : x(x), lz(0) {}
        Node operator + ( const Node &o ) const {
            return Node(x + o.x); 
        }
    }; 

    Node *seg; 
    int n; 
    Segtree( int n ) : n(n), seg(new Node[4*n]) {}

    void push( int node, int ti, int tf ){
        if( seg[node].lz == 0 ) return;
        int x = seg[node].lz; seg[node].lz = 0; 
        seg[node].x += x; 

        if( ti == tf ) return; 

        seg[2*node].lz += x; 
        seg[2*node + 1].lz += x; 
    }

    void update( int node, int ti, int tf, int qi, int qf, int x ){
        push(node, ti, tf); 
        if( qi > tf || ti > qf ) return; 
        if( qi <= ti && tf <= qf ){ seg[node].lz = x; push(node, ti, tf); return; }
        int l = 2*node, r = l + 1, tm = (ti + tf)/2; 
        update( l, ti, tm, qi, qf, x ); update( r, tm + 1, tf, qi, qf, x ); 
        seg[node] = seg[l] + seg[r]; 
    }

    void update( int l, int r, int x ){
        update( 1, 0, n - 1, l, r, x ); 
    }
    
    void update( int id, int x ){
        update( id, id, x ); 
    }

    Node query( int node, int ti, int tf, int qi, int qf ){
        push(node, ti, tf); 
        if( qi > tf || ti > qf ) return seg[0]; 
        if( qi <= ti && tf <= qf ) return seg[node]; 
        int l = 2*node, r = l + 1, tm = (ti + tf)/2; 
        return query(l, ti, tm, qi, qf) + query(r, tm + 1, tf, qi, qf); 
    }

    int query( int l, int r ){
        return query( 1, 0, n - 1, l, r ).x; 
    }

    int query( int id ){
        return query(id, id); 
    }
}; 

struct Event{
    int x1, x2, y, t; Event( int x1, int x2, int y, int t ) : x1(x1), x2(x2), y(y), t(t) {}
    bool operator < ( const Event &e ) const{
        if( y == e.y ) return abs(t) < abs(e.t); 
        return y < e.y; 
    }
};

ll solve_node( vector<Path> &paths, Segtree &seg ){
    int q = sz(paths);
    vector<Event> events; 
    for( auto &p : paths ){
        events.emplace_back( tin[p.a], tin[p.a], tin[p.b], 0 ); 
        events.emplace_back( tin[p.a], tout[p.a], tin[p.b] - 1, -1 ); 
        events.emplace_back( tin[p.a], tout[p.a], tout[p.b], 1 );
    }
    sort( events.begin(), events.end() ); 

    ll ans = 0; 
    for( auto &e : events ){
        if( e.t == 0 ) seg.update(e.x1, 1); 
        else ans += e.t*(seg.query(e.x1, e.x2));
    }
    for( auto &p : paths ) seg.update( tin[p.a], -1 );
    paths.clear();
    return ans - q; // evitar que um path conte a si mesmo
}

ll solve( int n, vector<Path> &paths ){
    sort( paths.begin(), paths.end() );

    int q = sz(paths); 
    ll ans = 1LL*q*(q - 1)/2; 

    Segtree tree(n), node(n); // Segtrees destinadas as queries na arvore e nos nodes individualmente

    vector<Path> cur; 

    for( auto &p : paths ){
        ans += tree.query(tin[p.a]) + tree.query(tin[p.b]) - tree.query(tin[p.lca]);

        tree.update( tin[p.lca], tout[p.lca], -1 );                      // atualizar lcas
        if( upper( p.a, p.b ) ) tree.update( tin[p.b], tout[p.b], 1 );   // atualizar bs
        else{
            if( !cur.empty() && cur.back().lca != p.lca ) ans += solve_node(cur, node); 
            cur.push_back(p);
        } 
    }

    ans += solve_node(cur, node);
    return ans; 
}

void solve(){
    int n, q, mode; cin >> n >> q >> mode; 
    FOR(i, 1, n){
        int a, b; cin >> a >> b; 
        a--; b--; 
        adj[a].push_back(b);
        adj[b].push_back(a);
    }

    dfs(0, 0);

    vector<Path> paths; 
    
    FOR(i, 0, q){
        int a, b; cin >> a >> b; 
        a--; b--; 
        paths.emplace_back( a, b );
    }
    
    ll ans = solve(n, paths); 

    if( mode ) cout << ans << '\n'; 
    else cout << (int)(ans == 1LL*q*(q - 1)/2) << '\n';
}

int main(){
    ios::sync_with_stdio(false); cin.tie(NULL); 
    solve();
}