#![allow(unused_imports)]
#![allow(clippy::many_single_char_names)]

// language: Rust(1.42.0)
// check available crates on AtCoder at "https://atcoder.jp/contests/language-test-202001"
// My Library Repo' is at "https://github.com/Loptall/prcn_lib"

/*
    そう甘くはないんだな〜w
*/

// from std...
use std::cmp::{
    max, min, Ordering,
    Ordering::{Equal, Greater, Less},
    Reverse,
};
use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
use std::convert::TryInto;
use std::mem::swap;
use std::num::{NonZeroU32, ParseIntError};
use std::ops::{
    Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
    Index, IndexMut, Mul, MulAssign, Neg, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub,
    SubAssign,
};
use std::process::exit;
use std::{f32, f64, i128, i16, i32, i64, i8, isize, u128, u16, u32, u64, u8, usize};

// Dep' crates are...
use itertools::*;
use itertools_num::*;
use lazy_static::lazy_static;
use maplit::{btreemap, btreeset, hashmap, hashset};
use num_bigint::{BigInt, BigUint};
use num_complex::Complex;
use num_integer::{binomial, gcd, lcm, multinomial, Integer};
use num_rational::Rational;
use num_traits::{clamp, one, pow, zero, Num, NumAssignOps, NumOps, One, Pow, Zero};
use permutohedron::Heap;
use proconio::{
    fastout, input, is_stdin_empty,
    marker::{Bytes, Chars, Isize1, Usize1},
};
use rand::random;

pub const MOD10E9_7: usize = 1000000007;
pub const MOD99_: usize = 998244353;
pub const MAX: usize = std::usize::MAX;
pub const PI: f64 = f64::consts::PI;
pub const A: u8 = 65;

#[derive(Debug, Clone)]
pub struct UnionFind {
    parent: Vec<usize>,
    size: Vec<usize>,
}

impl UnionFind {
    pub fn new(n: usize) -> Self {
        Self {
            parent: (0..n).collect::<Vec<usize>>(),
            size: vec![1; n],
        }
    }

    pub fn len(&self) -> usize {
        self.parent.len()
    }

    /// i が属する集合の親のインデックス
    pub fn find(&mut self, mut i: usize) -> usize {
        while self.parent[i] != i {
            self.parent[i] = self.find(self.parent[i]);
            i = self.parent[self.parent[i]];
        }
        i
    }

    /// a と b を繋ぐ
    pub fn unite(&mut self, a: usize, b: usize) -> bool {
        let mut a = self.find(a);
        let mut b = self.find(b);
        if a == b {
            return false;
        }
        if self.size[a] < self.size[b] {
            std::mem::swap(&mut a, &mut b);
        }
        self.size[a] += self.size[b];
        self.parent[b] = a;
        true
    }

    /// i が属する集合の要素数
    pub fn count(&self, i: usize) -> usize {
        self.size[self.parent[i]]
    }

    /// a と b が同一集合に属するか
    pub fn joint(&mut self, a: usize, b: usize) -> bool {
        self.find(a) == self.find(b)
    }

    /// i が属する集合の要素を列挙する
    pub fn get_group(&mut self, i: usize) -> Vec<usize> {
        let p = self.find(i);
        (0..self.len()).filter(|x| self.find(*x) == p).collect()
    }
}

// code...
// #[fastout]
fn main() {
    input! {
        n: usize, m: usize, k: usize,
        fr: [(Usize1, Usize1); m],
        bl: [(Usize1, Usize1); k]
    }

    let mut t = UnionFind::new(n);
    let mut q = vec![Vec::new(); n];
    for (a, b) in fr.iter() {
        t.unite(*a, *b);
        q[*a].push(*b);
        q[*b].push(*a);
    }
    let mut w = vec![Vec::new(); n];
    for (a, b) in bl.iter() {
        if t.joint(*a, *b) {
            w[*a].push(*b);
            w[*b].push(*a);
        }
    }

    let mut size = vec![0usize; n];
    for i in 0..n {
        size[t.find(i)] += 1;
    }

    for p in 0..n {
        let ans = size[t.find(p)] - q[p].len() - w[p].len() - 1;
        print!("{} ", ans);
    }
}


Measured memory_bytes: 21164