// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

using ll = long long;

using P = pair<ll,string>;

using Map = map<string,ll>;

using vl = vector<ll>;

using vvl = vector<vector<ll>>;



vector<ll> groupcounter(100005,0);

ll groups=0;

void dfs(ll n, ll groups,vvl &friendlist, vector<ll> &whichgroup){

    whichgroup[n]=groups;

    groupcounter[groups]++;

    for(ll i=0;i<friendlist[n].size();i++){

        ll k=friendlist[n][i];

        if(whichgroup[friendlist[n][i]]==-1)

        dfs(k,groups,friendlist,whichgroup);

    }

}



int main(){

    ll N;

    cin >> N;

    ll M;

    cin >> M;

    ll K;

    cin >> K;

    vector<ll> A(M,0);

    vector<ll> B(M,0);

    vector<ll> C(K,0);

    vector<ll> D(K,0);



    for(ll i=0;i<M;i++){

        cin>>A[i]>>B[i]

    ;}

    for(ll i=0;i<K;i++){

        cin>>C[i]>>D[i]

    ;}

    vector<vector<ll>> friendlist(N+1, vector<ll>(0));

    for(ll i=0;i<M;i++){

        friendlist[A[i]].emplace_back(B[i]);

        friendlist[B[i]].emplace_back(A[i])

    ;}



    vector<ll> whichgroup(N+1,-1);



    for(ll i=1;i<N+1;i++){

        if(whichgroup[i]==-1){

            groups++;

            dfs(i,groups,friendlist,whichgroup);

        }

    ;}

    vector<ll> ans(N+1,0);



    for(ll i=1;i<=N;i++){

        ans[i]=groupcounter[whichgroup[i]]-1

    ;}

    for(ll i=0;i<M;i++){

        if(whichgroup[A[i]]==whichgroup[B[i]]){

            ans[A[i]]--;

            ans[B[i]]--;

        }

    ;}

    for(ll i=0;i<K;i++){

        if(whichgroup[C[i]]==whichgroup[D[i]]){

            ans[C[i]]--;

            ans[D[i]]--;

        }

    ;}

    for(ll i=1;i<N+1;i++){

        cout<<ans[i];

        if(i<N)cout<<" ";

    ;}

    cout<<endl;





return 0;

}


// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

using namespace std;

using ll = long long;

using P = pair<string,ll>;

using Map = map<string,ll>;

using vl = vector<ll>;

using vvl = vector<vector<ll>>;





class UnionFind {

public:

    vector < ll > par; // 各元の親を表す配列

    vector < ll > siz; // 素集合のサイズを表す配列(1 で初期化)



    // Constructor

    UnionFind(ll sz_): par(sz_), siz(sz_, 1) {

        for (ll i = 0; i < sz_; ++i) par[i] = i; // 初期では親は自分自身

    }

    void init(ll sz_) {

        par.resize(sz_);

        siz.assign(sz_, 1);

        for (ll i = 0; i < sz_; ++i) par[i] = i; // 初期では親は自分自身

    }



    // Member Function

    // Find

    ll root(ll x) { // 根の検索

        while (par[x] != x) {

            x = par[x] = par[par[x]]; // x の親の親を x の親とする

        }

        return x;

    }



    // Union(Unite, Merge)

    bool unite(ll x, ll y) {

        x = root(x);

        y = root(y);

        if (x == y) return false;

        // merge technique（データ構造をマージするテク．小を大にくっつける）

        if (siz[x] < siz[y]) swap(x, y);

        siz[x] += siz[y];

        par[y] = x;

        return true;

    }



    bool same(ll x, ll y) { // 連結判定

        return root(x) == root(y);

    }



    ll size(ll x) { // 素集合のサイズ

        return siz[root(x)];

    }

};







int main(){

    ll N;

    cin >> N;

    ll M;

    cin >> M;

    ll K;

    cin >> K;

    UnionFind Tree(N+1);

    vector<ll> A(M+1,0);

    vector<ll> B(M+1,0);

    vector<ll> C(K+1,0);

    vector<ll> D(K+1,0);

    for(ll i=0;i<M;i++){

        cin>>A[i+1]>>B[i+1];

        Tree.unite(A[i+1],B[i+1]);

    ;}

    for(ll i=0;i<K;i++){

        cin>>C[i+1]>>D[i+1];

    ;}

    vector<ll> ans(N+1,0);

    for(ll i=1;i<=N;i++){

        ans[i]=Tree.size(i)-1

    ;}

    for(ll i=0;i<M;i++){

        ans[A[i+1]]--;

        ans[B[i+1]]--;

    ;}

    for(ll i=0;i<K;i++){

        if(Tree.same(C[i+1],D[i+1])){

            ans[C[i+1]]--;

            ans[D[i+1]]--;

        }

    ;}

    for(ll i=0;i<N;i++){

        cout<<ans[i+1]<<" ";

    ;}cout<<endl;





return 0;

}


// Fastest known solution for this problem: