#include <bits/stdc++.h>
       
using namespace std;
typedef long long ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return 1; } return 0; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return 1; } return 0; }
       

struct Edge {
  int from, to;
  Edge(){};
  Edge(int from, int to) : from(from), to(to) {}

  void scanFrom(std::istream& strm, int base = 1) {
    strm >> from >> to;
    if (base == 1) --from, --to;
  }

  Edge reverse() const { return Edge(to, from); }
};

inline std::istream& operator>>(std::istream& strm, Edge& t) {
  t.scanFrom(strm);
  return strm;
}
       
       

template <typename T>
struct WeightedEdge {
  int from, to;
  T _weight;
  WeightedEdge(){};
  WeightedEdge(int from, int to, T weight)
      : from(from), to(to), _weight(weight) {}

  void scanFrom(std::istream& strm, int base = 1) {
    strm >> from >> to >> _weight;
    if (base == 1) --from, --to;
  }

  T weight() const { return _weight; }

  WeightedEdge reverse() const { return WeightedEdge(to, from, _weight); }
};

template <typename T>
inline std::istream& operator>>(std::istream& strm, WeightedEdge<T>& t) {
  t.scanFrom(strm);
  return strm;
}

template <typename Edge>
class Digraph {
  int _E, _V;
  vector<vector<Edge>> _adjacencyList;

 public:
  int E() const { return _E; }

  int V() const { return _V; }
  int size() const { return _V; }

  Digraph() : _V(0), _E(0){};
  Digraph(int V, int E = 0) : _V(V), _E(E) { _adjacencyList.resize(V); }

  void addEdge(const Edge& e) {
    _adjacencyList[e.from].push_back(e);
    ++_E;
  }

  void addUndirectedEdge(const Edge& e) {
    _adjacencyList[e.from].push_back(e);
    _adjacencyList[e.to].push_back(e.reverse());
    ++_E;
  }

  void addNode() {
    ++_V;
    _adjacencyList.push_back(vector<Edge>());
  }

  void scanFrom(std::istream& strm, int base = 1) {
    if (_V == 0) strm >> _V;
    if (_E == 0) strm >> _E;
    _adjacencyList.resize(_V);
    for (int i = 0; i < _E; ++i) {
      Edge e;
      e.scanFrom(cin, base);
      assert(0 <= e.from < _V);
      assert(0 <= e.to < _V);
      addEdge(e);
    }
  }

  vector<Edge> operator[](int u) const { return _adjacencyList[u]; }
  vector<vector<Edge>>& adjacencyList() { return _adjacencyList; }
};

template <typename Edge>
inline std::istream& operator>>(std::istream& strm, Digraph<Edge>& t) {
  t.scanFrom(strm);
  return strm;
}
       
class UnionFindTree {
  vector<int> parent, rank, sz;

 public:
  int find(int x) {
    if (parent[x] != x) {
      parent[x] = find(parent[x]);
    }
    return parent[x];
  }

  UnionFindTree(int size) {
    parent.resize(size);
    rank.resize(size, 0);
    sz.resize(size, 1);
    for (int i = 0; i < size; i++) parent[i] = i;
  }
  bool unite(int x, int y) {
    x = find(x);
    y = find(y);
    if (x == y) return false;

    if (rank[x] < rank[y]) {
      parent[x] = y;
      sz[y] += sz[x];
    } else {
      parent[y] = x;
      sz[x] += sz[y];
      if (rank[x] == rank[y]) rank[x]++;
    }
    return true;
  }
  bool same(int x, int y) { return find(x) == find(y); }
  int size(int x) { return sz[find(x)]; }
};

int main() {
  int N, M, K;
  cin >> N >> M >> K;

  Digraph<Edge> GF(N), GB(N);
  for (int i = 0; i < (int)(M); ++i) {
    Edge e;
    cin >> e;
    GF.addUndirectedEdge(e);
  }

  for (int i = 0; i < (int)(K); ++i) {
    Edge e;
    cin >> e;
    GB.addUndirectedEdge(e);
  }

  UnionFindTree uf(N);
  vector<bool> used(N, false);
  function<void(int)> dfs = [&](int u) {
    used[u] = true;
    for (auto &e : GF[u]) {
      if (used[e.to]) continue;
      uf.unite(u, e.to);
      dfs(e.to);
    }
  };
  for (int i = 0; i < (int)(N); ++i) dfs(i);

  for (int i = 0; i < (int)(N); ++i) {
    if (i) cout << " ";
    int ans = uf.size(i) - 1;
    for (auto &e : GF[i]) ans -= uf.same(i, e.to);
    for (auto &e : GB[i]) ans -= uf.same(i, e.to);
    cout << ans;
  }
  cout << endl;

  return 0;
}


Measured memory_bytes: 19328