/**
 * @brief ユーザ定義リテラル
 * @author えびちゃん
 */

#ifndef H_int_literals
#define H_int_literals

#include <cstddef>
#include <cstdint>

constexpr intmax_t  operator ""_jd(unsigned long long n) { return n; }
constexpr uintmax_t operator ""_ju(unsigned long long n) { return n; }
constexpr size_t    operator ""_zu(unsigned long long n) { return n; }
constexpr ptrdiff_t operator ""_td(unsigned long long n) { return n; }

#endif  /* !defined(H_int_literals) */

/**
 * @brief 多次元 vector の作成
 * @author えびちゃん
 */

#ifndef H_make_vector
#define H_make_vector

#include <cstddef>
#include <type_traits>
#include <vector>

namespace detail {
  template <typename Tp, size_t N>
  std::vector<Tp> make_vector(
      std::vector<size_t>& sizes,
      typename std::enable_if<(N == 1), Tp const&>::type x
  ) {
    return std::vector<Tp>(sizes[0], x);
  }
  template <typename Tp, size_t N>
  auto make_vector(
      std::vector<size_t>& sizes,
      typename std::enable_if<(N > 1), Tp const&>::type x
  ) {
    size_t size = sizes[N-1];
    sizes.pop_back();
    return std::vector<decltype(make_vector<Tp, N-1>(sizes, x))>(
        size, make_vector<Tp, N-1>(sizes, x)
    );
  }
}  // detail::

template <typename Tp, size_t N>
auto make_vector(size_t const(&sizes)[N], Tp const& x = Tp()) {
  std::vector<size_t> s(N);
  for (size_t i = 0; i < N; ++i) s[i] = sizes[N-i-1];
  return detail::make_vector<Tp, N>(s, x);
}

#endif  /* !defined(H_make_vector) */

/**
 * @brief 素集合データ構造
 * @author えびちゃん
 */

#ifndef H_union_find
#define H_union_find

#include <cstddef>
#include <cstdint>
#include <utility>
#include <vector>

class disjoint_set {
public:
  using size_type = size_t;

private:
  mutable std::vector<intmax_t> M_c;

public:
  disjoint_set() = default;
  disjoint_set(disjoint_set const&) = default;
  disjoint_set(disjoint_set&&) = default;

  explicit disjoint_set(size_type n): M_c(n, -1) {}

  disjoint_set& operator =(disjoint_set const&) = default;
  disjoint_set& operator =(disjoint_set&&) = default;

  void reset() { M_c.assign(M_c.size(), -1); }

  size_type representative(size_type v) const {
    if (M_c[v] < 0) return v;
    return (M_c[v] = representative(M_c[v]));
  }

  bool unite(size_type u, size_type v) {
    u = representative(u);
    v = representative(v);
    if (u == v) return false;
    if (-M_c[u] > -M_c[v]) std::swap(u, v);
    M_c[v] += M_c[u];
    M_c[u] = v;
    return true;
  }

  bool equivalent(size_type u, size_type v) const {
    return (representative(u) == representative(v));
  }

  size_type size() const noexcept { return M_c.size(); }
  size_type count(size_type v) const {
    return -M_c[representative(v)];
  }
};

#endif  /* !defined(H_union_find) */

#include <cstdio>
#include <cstdint>
#include <algorithm>
#include <numeric>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

int main() {
  size_t n, m, k;
  scanf("%zu %zu %zu", &n, &m, &k);

  using edge_type = std::pair<size_t, size_t>;
  std::vector<edge_type> ab(m), cd(k);
  for (auto& p: ab) {
    scanf("%zu %zu", &p.first, &p.second);
    --p.first, --p.second;
  }
  for (auto& p: cd) {
    scanf("%zu %zu", &p.first, &p.second);
    --p.first, --p.second;
  }

  disjoint_set ds(n);
  for (auto const& p: ab) {
    size_t a, b;
    std::tie(a, b) = p;
    ds.unite(a, b);
  }

  std::vector<intmax_t> res(n);
  for (size_t i = 0; i < n; ++i) {
    res[i] = ds.count(i) - 1;
  }

  for (auto const& p: ab) {
    size_t a, b;
    std::tie(a, b) = p;
    --res[a], --res[b];
  }

  for (auto const& p: cd) {
    size_t c, d;
    std::tie(c, d) = p;
    if (ds.representative(c) == ds.representative(d))
      --res[c], --res[d];
  }

  for (size_t i = 0; i < n; ++i)
    printf("%jd%c", res[i], i+1<n? ' ': '\n');
}


Measured memory_bytes: 5504