Problem:
Score : 400 points

Problem Statement

An SNS has N users - User 1, User 2, \cdots, User N.

Between these N users, there are some relationships - M friendships and K blockships.

For each i = 1, 2, \cdots, M, there is a bidirectional friendship between User A_i and User B_i.

For each i = 1, 2, \cdots, K, there is a bidirectional blockship between User C_i and User D_i.

We define User a to be a friend candidate for User b when all of the following four conditions are satisfied:

a \neq b.

There is not a friendship between User a and User b.

There is not a blockship between User a and User b.

There exists a sequence c_0, c_1, c_2, \cdots, c_L consisting of integers between 1 and N (inclusive) such that c_0 = a, c_L = b, and there is a friendship between User c_i and c_{i+1} for each i = 0, 1, \cdots, L - 1.

For each user i = 1, 2, ... N, how many friend candidates does it have?

Constraints

All values in input are integers.

2 ≤ N ≤ 10^5

0 \leq M \leq 10^5

0 \leq K \leq 10^5

1 \leq A_i, B_i \leq N

A_i \neq B_i

1 \leq C_i, D_i \leq N

C_i \neq D_i

(A_i, B_i) \neq (A_j, B_j) (i \neq j)

(A_i, B_i) \neq (B_j, A_j)

(C_i, D_i) \neq (C_j, D_j) (i \neq j)

(C_i, D_i) \neq (D_j, C_j)

(A_i, B_i) \neq (C_j, D_j)

(A_i, B_i) \neq (D_j, C_j)

Input

Input is given from Standard Input in the following format:

N M K
A_1 B_1
\vdots
A_M B_M
C_1 D_1
\vdots
C_K D_K

Output

Print the answers in order, with space in between.

Sample Input 1

4 4 1
2 1
1 3
3 2
3 4
4 1

Sample Output 1

0 1 0 1

There is a friendship between User 2 and 3, and between 3 and 4. Also, there is no friendship or blockship between User 2 and 4. Thus, User 4 is a friend candidate for User 2.

However, neither User 1 or 3 is a friend candidate for User 2, so User 2 has one friend candidate.

Sample Input 2

5 10 0
1 2
1 3
1 4
1 5
3 2
2 4
2 5
4 3
5 3
4 5

Sample Output 2

0 0 0 0 0

Everyone is a friend of everyone else and has no friend candidate.

Sample Input 3

10 9 3
10 1
6 7
8 2
2 5
8 4
7 3
10 9
6 4
5 8
2 6
7 5
3 1

Sample Output 3

1 3 5 4 3 3 3 3 1 0

Solution in Rust (1.15.1) (judge verdict: Accepted)

// The main code is at the very bottom.

#[allow(unused_imports)]
#[macro_use]
pub mod spella {
  pub mod byte {
    pub use self::byte_char::*;
    pub use self::byte_str::*;
    pub use self::byte_string::*;
    pub use self::from_byte_str::*;

    mod byte_char {
      use std::fmt::{self, Debug, Display, Formatter};

      #[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
      pub struct ByteChar(pub u8);

      impl Debug for ByteChar {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
          write!(f, "b'{}'", self.0 as char)
        }
      }

      impl Display for ByteChar {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
          write!(f, "{}", self.0 as char)
        }
      }
    }

    mod byte_str {
      use spella::byte::{ByteChar, ByteString};
      use std::fmt::{self, Debug, Display, Formatter};
      use std::ops::{Deref, DerefMut};

      #[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
      pub struct ByteStr([ByteChar]);

      macro_rules! cast {
        (mut $x:expr, $($T:ty)=>*) => {
          unsafe { &mut *($x $(as *mut $T)*) }
        };
        ($x:expr, $($T:ty)=>*) => {
          unsafe { &*($x $(as *const $T)*) }
        };
      }

      impl ByteStr {
        pub fn from_bytes(s: &[u8]) -> &Self {
          cast!(s, [u8] => [ByteChar] => ByteStr)
        }

        pub fn from_bytes_mut(s: &mut [u8]) -> &mut Self {
          cast!(mut s, [u8] => [ByteChar] => ByteStr)
        }

        pub fn from_byte_chars(s: &[ByteChar]) -> &Self {
          cast!(s, [ByteChar] => ByteStr)
        }

        pub fn from_byte_chars_mut(s: &mut [ByteChar]) -> &mut Self {
          cast!(mut s, [ByteChar] => ByteStr)
        }

        pub fn as_byte_chars(&self) -> &[ByteChar] {
          &self.0
        }

        pub fn as_byte_chars_mut(&mut self) -> &mut [ByteChar] {
          &mut self.0
        }

        pub fn as_bytes(&self) -> &[u8] {
          cast!(self, ByteStr => [ByteChar] => [u8])
        }

        pub fn as_bytes_mut(&mut self) -> &mut [u8] {
          cast!(mut self, ByteStr => [ByteChar] => [u8])
        }
      }

      impl ToOwned for ByteStr {
        type Owned = ByteString;

        fn to_owned(&self) -> ByteString {
          ByteString::from(self.0.to_owned())
        }
      }

      impl Debug for ByteStr {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
          write!(f, "b\"")?;

          for &c in &self.0 {
            write!(f, "{}", c)?;
          }

          write!(f, "\"")
        }
      }

      impl Display for ByteStr {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
          for &c in &self.0 {
            write!(f, "{}", c)?;
          }

          Ok(())
        }
      }

      impl Deref for ByteStr {
        type Target = [ByteChar];

        fn deref(&self) -> &[ByteChar] {
          self.as_byte_chars()
        }
      }

      impl DerefMut for ByteStr {
        fn deref_mut(&mut self) -> &mut [ByteChar] {
          self.as_byte_chars_mut()
        }
      }
    }

    mod byte_string {
      use spella::byte::{ByteChar, ByteStr};

      use std::borrow::{Borrow, BorrowMut};
      use std::fmt::{self, Debug, Display, Formatter};
      use std::ops::{Deref, DerefMut};

      #[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
      pub struct ByteString(Vec<ByteChar>);

      impl ByteString {
        pub fn into_byte_chars(self) -> Vec<ByteChar> {
          self.0
        }

        pub fn as_byte_str(&self) -> &ByteStr {
          ByteStr::from_byte_chars(&self.0)
        }

        pub fn as_mut_byte_str(&mut self) -> &mut ByteStr {
          ByteStr::from_byte_chars_mut(&mut self.0)
        }
      }

      impl From<Vec<ByteChar>> for ByteString {
        fn from(s: Vec<ByteChar>) -> ByteString {
          ByteString(s)
        }
      }

      impl Borrow<ByteStr> for ByteString {
        fn borrow(&self) -> &ByteStr {
          self.as_byte_str()
        }
      }

      impl BorrowMut<ByteStr> for ByteString {
        fn borrow_mut(&mut self) -> &mut ByteStr {
          self.as_mut_byte_str()
        }
      }

      impl Debug for ByteString {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
          Debug::fmt(self.as_byte_str(), f)
        }
      }

      impl Display for ByteString {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
          Display::fmt(self.as_byte_str(), f)
        }
      }

      impl Deref for ByteString {
        type Target = ByteStr;

        fn deref(&self) -> &ByteStr {
          ByteStr::from_byte_chars(&self.0)
        }
      }

      impl DerefMut for ByteString {
        fn deref_mut(&mut self) -> &mut ByteStr {
          ByteStr::from_byte_chars_mut(&mut self.0)
        }
      }
    }

    mod from_byte_str {
      use spella::byte::{ByteChar, ByteStr, ByteString};

      use std::error::Error;
      use std::fmt::{self, Debug, Display, Formatter};
      use std::str::{self, FromStr, Utf8Error};

      pub trait FromByteStr: Sized {
        type Err;

        fn from_byte_str(s: &ByteStr) -> Result<Self, Self::Err>;
      }

      macro_rules! fn_description {
        () => {
          fn description(&self) -> &str {
            "description() is deprecated; use Display"
          }
        };
      }

      #[derive(Debug)]
      pub struct ParseByteCharError(ParseByteCharErrorKind);

      #[derive(Debug)]
      enum ParseByteCharErrorKind {
        EmptyByteStr,
        TooManyByteChars,
      }

      impl Display for ParseByteCharError {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
          use self::ParseByteCharErrorKind::*;

          f.write_str(match self.0 {
            EmptyByteStr => "empty `ByteStr`",
            TooManyByteChars => "too many `ByteChar`s",
          })
        }
      }

      impl Error for ParseByteCharError {
        fn_description! {}
      }

      impl FromByteStr for ByteChar {
        type Err = ParseByteCharError;

        fn from_byte_str(s: &ByteStr) -> Result<Self, Self::Err> {
          use self::ParseByteCharErrorKind::*;

          match s.len() {
            1 => Ok(unsafe { *s.get_unchecked(0) }),
            0 => Err(ParseByteCharError(EmptyByteStr)),
            _ => Err(ParseByteCharError(TooManyByteChars)),
          }
        }
      }

      #[derive(Debug)]
      pub enum ParseByteStringError {}

      impl Display for ParseByteStringError {
        fn fmt(&self, _: &mut Formatter) -> fmt::Result {
          match *self {}
        }
      }

      impl Error for ParseByteStringError {
        fn_description! {}
      }

      impl FromByteStr for ByteString {
        type Err = ParseByteStringError;

        fn from_byte_str(s: &ByteStr) -> Result<Self, Self::Err> {
          Ok(ByteString::from(s.to_vec()))
        }
      }

      pub struct ParseFromStrError<T: FromStr>(ParseFromStrErrorKind<T>);

      enum ParseFromStrErrorKind<T: FromStr> {
        Utf8Error(Utf8Error),
        FromStrError(T::Err),
      }

      impl<T: FromStr> Debug for ParseFromStrError<T>
      where
        T::Err: Debug,
      {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
          use self::ParseFromStrErrorKind::*;

          match self.0 {
            Utf8Error(ref err) => f.debug_tuple("Utf8Error").field(err).finish(),
            FromStrError(ref err) => f.debug_tuple("FromStrError").field(err).finish(),
          }
        }
      }

      impl<T: FromStr> Display for ParseFromStrError<T>
      where
        T::Err: Display,
      {
        fn fmt(&self, f: &mut Formatter) -> fmt::Result {
          use self::ParseFromStrErrorKind::*;

          match self.0 {
            Utf8Error(ref err) => write!(f, "{}", err),
            FromStrError(ref err) => write!(f, "{}", err),
          }
        }
      }

      impl<T: FromStr> Error for ParseFromStrError<T>
      where
        T::Err: Debug + Display,
      {
        fn_description! {}
      }

      impl<T: FromStr> FromByteStr for T {
        type Err = ParseFromStrError<T>;

        fn from_byte_str(s: &ByteStr) -> Result<T, Self::Err> {
          use self::ParseFromStrErrorKind::*;

          str::from_utf8(s.as_bytes())
            .map_err(|e| ParseFromStrError(Utf8Error(e)))
            .and_then(|s| s.parse().map_err(|e| ParseFromStrError(FromStrError(e))))
        }
      }
    }
  }

  pub mod io {
    pub use self::scanner::*;

    mod scanner {
      use spella::byte::{ByteStr, FromByteStr};

      use std::io::{self, BufRead};

      #[derive(Debug)]
      pub struct Scanner<R> {
        reader: R,
        buf: Vec<u8>,
        pos: usize,
      }

      const INITIAL_CAPACITY: usize = 32;

      impl<R: BufRead> Scanner<R> {
        pub fn new(reader: R) -> Self {
          Scanner {
            reader: reader,
            buf: Vec::with_capacity(INITIAL_CAPACITY),
            pos: 0,
          }
        }

        pub fn next<T: FromByteStr>(&mut self) -> io::Result<Result<T, T::Err>> {
          self.next_byte_str().map(T::from_byte_str)
        }

        pub fn next_byte_str(&mut self) -> io::Result<&ByteStr> {
          if self.buf.is_empty() {
            self.read_line()?;
          }

          loop {
            match self.buf.get(self.pos) {
              Some(&b' ') => self.pos += 1,
              Some(&b'\n') => self.read_line()?,
              Some(_) => break,
              None => return Err(io::Error::from(io::ErrorKind::UnexpectedEof)),
            }
          }

          let start = self.pos;
          self.pos += 1;

          loop {
            match self.buf.get(self.pos) {
              Some(&b' ') | Some(&b'\n') | None => break,
              Some(_) => self.pos += 1,
            }
          }

          Ok(ByteStr::from_bytes(&self.buf[start..self.pos]))
        }

        fn read_line(&mut self) -> io::Result<()> {
          self.buf.clear();
          self.pos = 0;
          self.reader.read_until(b'\n', &mut self.buf)?;

          Ok(())
        }
      }
    }
  }
}

pub mod stopgap {
  use std::fmt::{self, Debug, Display, Formatter};
  use std::hash::{Hash, Hasher};
  use std::iter::{Product, Sum};
  use std::marker::PhantomData;
  use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};

  pub trait Constant<T> {
    fn get() -> T;
  }

  pub enum _1000000007 {}

  impl Constant<u32> for _1000000007 {
    fn get() -> u32 {
      1000000007
    }
  }

  pub struct ModU32<Mod> {
    _phantom: PhantomData<fn() -> Mod>,
    repr: u32,
  }

  impl<Mod: Constant<u32>> Clone for ModU32<Mod> {
    fn clone(&self) -> Self {
      Self::from_repr(self.repr)
    }
  }

  impl<Mod: Constant<u32>> Copy for ModU32<Mod> {}

  impl<Mod: Constant<u32>> PartialEq for ModU32<Mod> {
    fn eq(&self, other: &Self) -> bool {
      self.repr.eq(&other.repr)
    }
  }

  impl<Mod: Constant<u32>> Eq for ModU32<Mod> {}

  impl<Mod: Constant<u32>> Default for ModU32<Mod> {
    fn default() -> Self {
      ModU32::from_repr(u32::default())
    }
  }

  impl<Mod: Constant<u32>> Hash for ModU32<Mod> {
    fn hash<H>(&self, state: &mut H)
    where
      H: Hasher,
    {
      self.repr.hash(state);
    }
  }

  impl<Mod: Constant<u32>> Debug for ModU32<Mod> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
      Debug::fmt(&self.repr, f)
    }
  }

  impl<Mod: Constant<u32>> Display for ModU32<Mod> {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
      Display::fmt(&self.repr, f)
    }
  }

  impl<Mod: Constant<u32>> ModU32<Mod> {
    pub fn new(value: u32) -> Self {
      Self::from_repr(value % Mod::get())
    }

    fn from_repr(repr: u32) -> Self {
      debug_assert!(repr < Mod::get());
      ModU32 {
        _phantom: PhantomData,
        repr: repr,
      }
    }

    pub fn repr(self) -> u32 {
      self.repr
    }

    pub fn inverse(self) -> Self {
      let mut a = self.repr as i64;
      let mut b = Mod::get() as i64;
      let mut u = 1i64;
      let mut v = 0i64;
      while b != 0 {
        let t = a / b;
        a -= t * b;
        ::std::mem::swap(&mut a, &mut b);
        u -= t * v;
        ::std::mem::swap(&mut u, &mut v);
      }
      u %= Mod::get() as i64;
      if u < 0 {
        u += Mod::get() as i64;
      }
      Self::from_repr(u as u32)
    }

    pub fn pow(mut self, mut n: u32) -> Self {
      let mut acc = ModU32::from_repr(1);
      while n > 0 {
        if n % 2 == 1 {
          acc *= self;
        }
        self *= self;
        n /= 2;
      }
      acc
    }
  }

  impl<Mod: Constant<u32>> Add for ModU32<Mod> {
    type Output = Self;

    fn add(mut self, rhs: Self) -> Self {
      self += rhs;
      self
    }
  }

  impl<Mod: Constant<u32>> AddAssign for ModU32<Mod> {
    fn add_assign(&mut self, rhs: Self) {
      self.repr += rhs.repr;
      if self.repr >= Mod::get() {
        self.repr -= Mod::get();
      }
    }
  }

  impl<Mod: Constant<u32>> Sub for ModU32<Mod> {
    type Output = Self;

    fn sub(mut self, rhs: Self) -> Self {
      self -= rhs;
      self
    }
  }

  impl<Mod: Constant<u32>> SubAssign for ModU32<Mod> {
    fn sub_assign(&mut self, rhs: Self) {
      if self.repr < rhs.repr {
        self.repr += Mod::get();
      }
      self.repr -= rhs.repr;
    }
  }

  impl<Mod: Constant<u32>> Mul for ModU32<Mod> {
    type Output = Self;

    fn mul(self, rhs: Self) -> Self {
      Self::from_repr((self.repr as u64 * rhs.repr as u64 % Mod::get() as u64) as u32)
    }
  }

  impl<Mod: Constant<u32>> MulAssign for ModU32<Mod> {
    fn mul_assign(&mut self, rhs: Self) {
      *self = *self * rhs;
    }
  }

  impl<Mod: Constant<u32>> Div for ModU32<Mod> {
    type Output = Self;

    fn div(self, rhs: Self) -> Self {
      self * rhs.inverse()
    }
  }

  impl<Mod: Constant<u32>> DivAssign for ModU32<Mod> {
    fn div_assign(&mut self, rhs: Self) {
      *self *= rhs.inverse();
    }
  }

  impl<Mod: Constant<u32>> Sum for ModU32<Mod> {
    fn sum<I>(iter: I) -> Self
    where
      I: Iterator<Item = Self>,
    {
      let mut acc = ModU32::from_repr(0);
      for x in iter {
        acc += x;
      }
      acc
    }
  }

  impl<Mod: Constant<u32>> Product for ModU32<Mod> {
    fn product<I>(iter: I) -> Self
    where
      I: Iterator<Item = Self>,
    {
      let mut acc = ModU32::from_repr(1);
      for x in iter {
        acc *= x;
      }
      acc
    }
  }

  pub fn mod_pow<Mod: Constant<u32>>(base: u32, n: u32) -> ModU32<Mod> {
    ModU32::new(base).pow(n)
  }

  pub fn mod_binomial<Mod: Constant<u32>>(mut n: u32, mut k: u32) -> ModU32<Mod> {
    let mut acc = ModU32::from_repr(1);
    while k != 0 {
      {
        let n = n % Mod::get();
        let k = k % Mod::get();
        if n < k {
          return ModU32::from_repr(0);
        }
        acc *= (n - k + 1..n + 1).map(ModU32::from_repr).product();
        acc /= (1..k + 1).map(ModU32::from_repr).product();
      }
      n /= Mod::get();
      k /= Mod::get();
    }
    acc
  }
}

#[allow(unused_imports)]
use stopgap::*;

mod prelude {
  pub use spella::byte::{ByteChar, ByteStr, ByteString};
  pub use std::collections::*;
  pub use std::io::prelude::*;
  pub use std::iter::FromIterator;
  pub use std::marker::PhantomData;
  pub use std::num::Wrapping;
  pub use std::ops::{Range, RangeFrom, RangeTo};
  pub use std::{cell, cmp, f64, i32, i64, isize, iter, mem, rc, str, time, u32, u64, usize};
}

use prelude::*;

const CUSTOM_STACK_SIZE_MEBIBYTES: Option<usize> = None;

fn main() {
  fn exec_solver() {
    let stdin = std::io::stdin();
    let stdout = std::io::stdout();
    #[cfg(not(debug_assertions))]
    let mut writer = std::io::BufWriter::new(stdout.lock());
    #[cfg(debug_assertions)]
    let mut writer = stdout.lock();
    solve(stdin.lock(), &mut writer);
    writer.flush().unwrap();
  }

  if let Some(stack_size_mebibytes) = CUSTOM_STACK_SIZE_MEBIBYTES {
    std::thread::Builder::new()
      .name("exec_solver".to_owned())
      .stack_size(stack_size_mebibytes * 1024 * 1024)
      .spawn(exec_solver)
      .unwrap()
      .join()
      .unwrap();
  } else {
    exec_solver();
  }
}

fn solve<R: BufRead, W: Write>(reader: R, mut writer: W) {
  let mut _scanner = spella::io::Scanner::new(reader);

  #[allow(unused_macros)]
  macro_rules! scan {
    ($T:ty) => {
      _scanner.next::<$T>().unwrap().unwrap()
    };
    ($($T:ty),+) => {
      ($(scan!($T)),+)
    };
    ($($T:ty),+; $n:expr $(; $m:expr)*) => {{
      (0..$n).map(|_| scan!($($T),+ $(; $m)*)).collect::<Vec<_>>()
    }};
  }

  #[allow(unused_macros)]
  macro_rules! scan_iter {
    ($($T:ty),+; $n:expr) => {
      (0..$n).map(|_| scan!($($T),+))
    };
  }

  #[allow(unused_macros)]
  macro_rules! print {
    ($fmt:expr) => {
      write!(writer, $fmt).unwrap()
    };
    ($fmt:expr, $($arg:tt)*) => {
      write!(writer, $fmt, $($arg)*).unwrap()
    };
  }

  #[allow(unused_macros)]
  macro_rules! println {
    ($fmt:expr) => {
      writeln!(writer, $fmt).unwrap()
    };
    ($fmt:expr, $($arg:tt)*) => {
      writeln!(writer, $fmt, $($arg)*).unwrap()
    };
  }

  #[allow(unused_macros)]
  macro_rules! eprint {
    ($fmt:expr) => {
      #[cfg(debug_assertions)]
      write!(std::io::stderr(), $fmt).unwrap()
    };
    ($fmt:expr, $($arg:tt)*) => {
      #[cfg(debug_assertions)]
      write!(std::io::stderr(), $fmt, $($arg)*).unwrap()
    };
  }

  #[allow(unused_macros)]
  macro_rules! eprintln {
    ($fmt:expr) => {
      #[cfg(debug_assertions)]
      writeln!(std::io::stderr(), $fmt).unwrap()
    };
    ($fmt:expr, $($arg:tt)*) => {
      #[cfg(debug_assertions)]
      writeln!(std::io::stderr(), $fmt, $($arg)*).unwrap()
    };
  }

  #[allow(unused_macros)]
  macro_rules! dbg {
    ($($x:expr),+) => {{
      eprintln!(concat!("[{}:{}] ", $(stringify!($x), " = {:?}; "),+), file!(), line!(), $($x),+);
    }};
  }

  #[allow(dead_code)]
  mod union_find {
    use std::mem;

    #[derive(Debug, Clone)]
    pub struct UnionFind {
      nodes: Vec<Node>,
    }

    #[derive(Debug, Clone)]
    struct Node {
      parent: usize,
      len: usize,
    }

    impl UnionFind {
      pub fn new(len: usize) -> Self {
        UnionFind {
          nodes: (0..len).map(|i| Node { parent: i, len: 1 }).collect(),
        }
      }

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

      pub fn unite_sets(&mut self, a: usize, b: usize) -> bool {
        let mut a = self.find_set(a);
        let mut b = self.find_set(b);
        if a == b {
          return false;
        }
        if self.nodes[a].len < self.nodes[b].len {
          mem::swap(&mut a, &mut b);
        }
        self.nodes[a].len += self.nodes[b].len;
        self.nodes[b].parent = a;
        true
      }

      pub fn find_set(&mut self, mut index: usize) -> usize {
        while !self.is_root(index) {
          let grandparent = self.nodes[self.nodes[index].parent].parent;
          self.nodes[index].parent = grandparent;
          index = grandparent;
        }
        index
      }

      pub fn belong_to_same_set(&mut self, a: usize, b: usize) -> bool {
        self.find_set(a) == self.find_set(b)
      }

      pub fn set_len(&mut self, index: usize) -> usize {
        let i = self.find_set(index);
        self.nodes[i].len
      }

      fn is_root(&self, index: usize) -> bool {
        self.nodes[index].parent == index
      }
    }
  }

  let (n, m, k) = scan!(usize, usize, usize);
  let mut f_g = vec![vec![]; n];
  for (a, b) in scan_iter!(usize, usize; m) {
    f_g[a - 1].push(b - 1);
    f_g[b - 1].push(a - 1);
  }
  let mut b_g = vec![vec![]; n];
  for (c, d) in scan_iter!(usize, usize; k) {
    b_g[c - 1].push(d - 1);
    b_g[d - 1].push(c - 1);
  }

  let mut f_uf = union_find::UnionFind::new(n);
  for s in 0..n {
    for &t in &f_g[s] {
      f_uf.unite_sets(s, t);
    }
  }

  for s in 0..n {
    let mut set = f_g[s].iter().cloned().collect::<HashSet<_>>();
    for &t in &b_g[s] {
      if f_uf.belong_to_same_set(s, t) {
        set.insert(t);
      }
    }
    let ans = f_uf.set_len(s) - 1 - set.len();
    print!("{}", ans);
    if s + 1 < n {
      print!(" ");
    }
  }
  println!("");
}