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: Runtime Error)

use std::io::*;
use std::str::FromStr;
use std::cmp::Ordering;
use std::collections::HashMap;
use std::collections::HashSet;
use std::hash::Hash;
use std::fmt::Debug;
use std::cmp::Eq;

fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char) 
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

pub trait BinarySearch<T> {
    fn lower_bound(&self, x: &T) -> usize;
    fn upper_bound(&self, x: &T) -> usize;
    fn bsearch(&self, x: &T) -> Option<usize>;
}

impl<T: Ord> BinarySearch<T> for [T] {
    fn lower_bound(&self, x: &T) -> usize {
        let mut low = 0;
        let mut high = self.len();

        while low != high {
            let mid = (low + high) / 2;
            match self[mid].cmp(x) {
                Ordering::Less => {
                    low = mid + 1;
                }
                Ordering::Equal | Ordering::Greater => {
                    high = mid;
                }
            }
        }
        low
    }

    fn upper_bound(&self, x: &T) -> usize {
        let mut low = 0;
        let mut high = self.len();

        while low != high {
            let mid = (low + high) / 2;
            match self[mid].cmp(x) {
                Ordering::Less | Ordering::Equal => {
                    low = mid + 1;
                }
                Ordering::Greater => {
                    high = mid;
                }
            }
        }
        low
    }

    fn bsearch(&self, x: &T) -> Option<usize> {
        let lower_idx = self.lower_bound(x);
        if lower_idx < self.len() && self[lower_idx] == *x {
            return Some(lower_idx);
        }
        return None;
    }
}


trait GraphMethods<T> {
    fn new() -> Graph<T>;
    fn add_node(&mut self, x: &T);
    fn add_di_edge(&mut self, x: &T, y: &T);
    fn add_ud_edge(&mut self, x: &T, y: &T);
    fn get_edged_nodes(&self, x: &T) -> HashSet<T>;
    fn get_linked_nodes(&self, x: &T) -> HashSet<T>;
    fn cnt_edged_nodes(&self, x: &T) -> usize;
    fn cnt_linked_nodes(&self, x: &T) -> usize;
}

struct Graph<T> {
    g: HashMap<T, HashSet<T>>,  // g[1] = [2, 3]: ノード 1 が 2 と 3 と繋がっている
    nodes: HashSet<T>,
}

impl<T: Hash + Ord + Eq + Copy + Debug> GraphMethods<T> for Graph<T> {
    fn new() -> Graph<T> {
        return Graph {
            g: HashMap::new(),
            nodes: HashSet::new(),
        };
    }
    fn add_node(&mut self, x: &T) {
        if self.nodes.insert(*x) {
            self.g.insert(*x, HashSet::new());
        }
    }
    fn add_di_edge(&mut self, x: &T, y: &T){
        self.add_node(x);
        let mut set = self.g[x].clone();
        set.insert(*y);
        self.g.insert(*x, set);
    }
    fn add_ud_edge(&mut self, x: &T, y: &T){
        self.add_di_edge(x, y);
        self.add_di_edge(y, x);
    }
    fn get_edged_nodes(&self, x: &T) -> HashSet<T> {
        if let Some(set) = self.g.get(x) {
            return set.clone();
        } else {
            return HashSet::new();
        }
    }
    fn get_linked_nodes(&self, x: &T) -> HashSet<T> {
        let mut searched: HashSet<T> = HashSet::new();

        fn _cnt_linked_node<T: Hash + Ord + Eq + Copy + Debug>(x: &T, g: HashMap<T, HashSet<T>>, searched: &mut HashSet<T>) -> usize {
            searched.insert(*x);
            let mut cnt = 0;
            let ref gx = g[x];
            for y in gx.iter() {
                if !searched.contains(&y){
                    cnt += 1;
                    searched.insert(*y);
                    cnt += _cnt_linked_node(y, g.clone(), searched);
                }
            }
            return cnt;
        }
        _cnt_linked_node(x, self.g.clone(), &mut searched);

        return searched;
    }
    fn cnt_edged_nodes(&self, x: &T) -> usize {
        return self.get_edged_nodes(x).len();
    }
    fn cnt_linked_nodes(&self, x: &T) -> usize {
        return self.get_linked_nodes(x).len();
    }
}


fn main() {
    let n: usize = read();
    let m: usize = read();
    let k: usize = read();

    let mut ai: Vec<usize> = Vec::new();
    let mut bi: Vec<usize> = Vec::new();
    for _ in 0..m {
        ai.push(read());
        bi.push(read());
    }

    let mut ci: Vec<usize> = Vec::new();
    let mut di: Vec<usize> = Vec::new();
    for _ in 0..k {
        ci.push(read());
        di.push(read());
    }

    let mut friend_graph: Graph<usize> = Graph::new();
    let mut block_graph: Graph<usize> = Graph::new();
    for i in 0..m {
        friend_graph.add_ud_edge(&ai[i], &bi[i]);
    }
    for i in 0..k {
        block_graph.add_ud_edge(&ci[i], &di[i]);
    }

    let mut ans: Vec<usize> = Vec::new();
    for i in 1..n+1 {
        let frined_linked_nodes = friend_graph.get_linked_nodes(&i);
        let friend_edged_nodes = friend_graph.get_edged_nodes(&i);
        let block_edged_nodes = block_graph.get_edged_nodes(&i);
        let to_remove_nodes: HashSet<usize> = friend_edged_nodes.union(&block_edged_nodes).map(|n| *n).collect();
        let friend_rel_nodes: HashSet<&usize> = frined_linked_nodes.difference(&to_remove_nodes).collect();
        let cnt = friend_rel_nodes.len() - 1;
        ans.push(cnt);
    }

    let ans: Vec<String> = ans.into_iter().map(|i| i.to_string()).collect();
    println!("{}", ans.join(" "));
}