#include <bits/stdc++.h>
#define int long long
#define ll long long
using ull = unsigned long long;
using namespace std;
const int INF = 1e10;
const int MOD = 1e9 + 7;
#define dump(x)                             \
    if (dbg) {                              \
        cerr << #x << " = " << (x) << endl; \
    }
#define overload4(_1, _2, _3, _4, name, ...) name
#define FOR1(n) for (ll i = 0; i < (n); ++i)
#define FOR2(i, n) for (ll i = 0; i < (n); ++i)
#define FOR3(i, a, b) for (ll i = (a); i < (b); ++i)
#define FOR4(i, a, b, c) for (ll i = (a); i < (b); i += (c))
#define FOR(...) overload4(__VA_ARGS__, FOR4, FOR3, FOR2, FOR1)(__VA_ARGS__)
#define FORR(i, a, b) for (int i = (a); i <= (b); ++i)
template <class T>
bool chmin(T& a, const T& b) {
    if (a > b) {
        a = b;
        return 1;
    } else
        return 0;
}
template <class T>
bool chmax(T& a, const T& b) {
    if (a < b) {
        a = b;
        return 1;
    } else
        return 0;
}
#define pb push_back
#define mp make_pair
#define lb lower_bound
#define ub upper_bound
#define all(v) (v).begin(), (v).end()
#define SZ(x) ((int)(x).size())
#define P pair<int, int>
#define V vector<int>
//#define S set<int>
#define itn int
bool dbg = false;

//UnionFind
//How to use
//unite : xとyの木を併合
//root : データxが属する木の根を再帰で得る：root(x) = {xの木の根}
//same : 2つのデータx, yが属する木が同じならtrueを返す
//find(k): 要素 k が属する集合を求める
//size(k) : 要素 k が属する集合の要素の数を求める
struct UnionFind {
    vector<int> par;  // par[i]:iの親の番号　(例) par[3] = 2 : 3の親が2

    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;
    }

    int find(int k) {
        if (par[k] < 0)
            return (k);
        return (par[k] = find(par[k]));
    }

    int size(int k) {
        return (-par[find(k)]);
    }
};
//example
/*
int main() {
  int N, Q;
  scanf("%d %d", &N, &Q);
  UnionFind uf(N);
  while(Q--) {
    int t, x, y;
    scanf("%d %d %d", &t, &x, &y);
    if(t == 0) uf.unite(x, y);
    else printf("%d\n", uf.find(x) == uf.find(y));
  }
}
*/

int N, M, K;
int A[101010], B[101010], C[101010], D[101010];
itn ans[101010];
itn t[101010];

void solve() {
    UnionFind uf(N);
    FOR(i, 0, M)
    uf.unite(A[i], B[i]);

    FOR(i, 0, N) {
        t[uf.root(i)]++;
    }
    FOR(i, 0, N) {
        ans[i] = t[uf.root(i)] - 1;
    }
    FOR(M) {
        if (uf.same(A[i], B[i])) {
            ans[A[i]]--;
            ans[B[i]]--;
        }
    }
    FOR(K) {
        if (uf.same(C[i], D[i])) {
            ans[C[i]]--;
            ans[D[i]]--;
        }
    }
    FOR(N)
        cout << ans[i] << " ";
    cout << endl;
}

signed main() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cin >> N >> M >> K;
    FOR(M) {
        cin >> A[i] >> B[i];
        A[i]--;
        B[i]--;
    }
    FOR(K) {
        cin >> C[i] >> D[i];
        C[i]--;
        D[i]--;
    }
    solve();
    return 0;
}


Measured memory_bytes: 6272