#include <bits/stdc++.h>

using namespace std;
using ll = int64_t;
using pii = pair<int, int>;
using pli = pair<ll, int>;
using mii = map<int, int>;
using vi = vector<int>;
using vii = vector<vi>;
using vl = vector<ll>;
using vll = vector<vl>;
using tpi = tuple<int, int, int>;

using vqi = vector<queue<int>>;
using vpi = vector<pii>;
using bs = bitset<60>;
using vbi = vector<bs>;

ll gcd(ll a, ll b) {
    if (a < b) {
        swap(a, b);
    }

    /* ユークリッドの互除法 */
    ll r = a % b;
    while (r != 0) {
        a = b;
        b = r;
        r = a % b;
    }
    return b;
}

ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }

constexpr int64_t __pow_mod(int64_t n, int64_t p, int64_t mod) noexcept {
    if (p == 0) {
        return 1;
    }
    if (p % 2 == 0) {
        int64_t t = __pow_mod(n, p / 2, mod);
        return (t * t) % mod;
    }
    return (n * (__pow_mod(n, p - 1, mod) % mod)) % mod;
}

constexpr int64_t pow_mod(int64_t n, int64_t p, int64_t mod) noexcept {
    int64_t res = __pow_mod(n, p, mod);
    if (res == 0) {
        res = mod;
    }
    return res;
}

constexpr int64_t nCr_mod(int64_t n, int64_t r, int64_t mod) noexcept {
    int64_t count = 1;
    auto a = r;
    for (auto i = n; i > n - r; i--) {
        count *= i;
        if (count % mod != 0) {
            count %= mod;
        }
        int64_t inv = pow_mod(a, mod - 2, mod);
        count *= inv;
        if (count % mod != 0) {
            count %= mod;
        }
        a--;
    }
    return count;
}

struct UnionFind {
    vector<int> par; // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2

    explicit UnionFind(int N) : par(N) { //最初は全てが根であるとして初期化
        for (int i = 0; i < N; i++) par[i] = i;
    }

    int root(int x) { // データxが属する木の根を再帰で得る：root(x) = {xの木の根}
        if (par[x] == x) return x;
        return par[x] = root(par[x]);
    }

    void unite(int x, int y) { // xとyの木を併合
        int rx = root(x); //xの根をrx
        int ry = root(y); //yの根をry
        if (rx == ry) return; //xとyの根が同じ(=同じ木にある)時はそのまま
        par[rx] = ry; //xとyの根が同じでない(=同じ木にない)時：xの根rxをyの根ryにつける
    }

    bool same(int x, int y) { // 2つのデータx, yが属する木が同じならtrueを返す
        int rx = root(x);
        int ry = root(y);
        return rx == ry;
    }
};

void solve(long long N, long long M, long long K, std::vector<long long> A,
           std::vector<long long> B, std::vector<long long> C,
           std::vector<long long> D) {
    UnionFind f(N);
    vector<list<int>> v_list(N);
    for (int i = 0; i < M; i++) {
        f.unite(A[i] - 1, B[i] - 1);
        v_list[A[i] - 1].push_front(B[i] - 1);
        v_list[B[i] - 1].push_front(A[i] - 1);
    }

    for (int i = 0; i < K; i++) {
        if (f.same(C[i] - 1, D[i] - 1)) {
            v_list[C[i] - 1].push_front(D[i] - 1);
            v_list[D[i] - 1].push_front(C[i] - 1);
        }
    }

    mii m;
    for (int i = 0; i < N; i++) {
        m[f.root(i)]++;
    }

    for (int i = 0; i < N; i++) {
        int ans = m[f.root(i)] - v_list[i].size() - 1;
        cout << ans;
        if (i != N - 1) {
            cout << " ";
        }
    }
    cout << endl;
}

// Generated by 1.1.6 https://github.com/kyuridenamida/atcoder-tools  (tips: You
// use the default template now. You can remove this line by using your custom
// template)
int main() {
    long long N;
    std::cin >> N;
    long long M;
    std::cin >> M;
    long long K;
    std::cin >> K;
    std::vector<long long> A(M);
    std::vector<long long> B(M);
    for (int i = 0; i < M; i++) {
        std::cin >> A[i];
        std::cin >> B[i];
    }
    std::vector<long long> C(K);
    std::vector<long long> D(K);
    for (int i = 0; i < K; i++) {
        std::cin >> C[i];
        std::cin >> D[i];
    }
    solve(N, M, K, std::move(A), std::move(B), std::move(C), std::move(D));
    return 0;
}


Measured memory_bytes: 22656