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



Sample input:
4 4 1
2 1
1 3
3 2
3 4
4 1


Sample output:
0 1 0 1

Submission status: Accepted

Solution code:
from heapq import heappush, heappop, heapify
from collections import deque, defaultdict, Counter
import itertools
from itertools import permutations, combinations, accumulate
import sys
import bisect
import string
import math
import time


def I(): return int(input())


def MI(): return map(int, input().split())


def S(): return input()


def MS(): return map(str, input().split())


def LI(): return [int(i) for i in input().split()]


def LI_(): return [int(i)-1 for i in input().split()]


def StoI(): return [ord(i)-97 for i in input()]


def ItoS(nn): return chr(nn+97)


def input(): return sys.stdin.readline().rstrip()


def show(*inp, end='\n'):
    if show_flg:
        print(*inp, end=end)


YNL = {False: 'No', True: 'Yes'}
YNU = {False: 'NO', True: 'YES'}
MOD = 10**9+7
inf = float('inf')
IINF = 10**10
l_alp = string.ascii_lowercase
u_alp = string.ascii_uppercase
ts = time.time()
# sys.setrecursionlimit(10**6)
nums = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10']


# show_flg = True
show_flg = False


class UnionFind(object):
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots()),


def main():
    N, M, K = MI()
    uf = UnionFind(N+1)
    friends = {k: set() for k in range(1, N+1)}
    blocks = {k: set() for k in range(1, N+1)}
    # graph = [[] for i in range(N+1)]

    for i in range(M):
        A, B = MI()
        friends[A].add(B)
        friends[B].add(A)
        uf.union(A, B)

    for i in range(K):
        C, D = MI()
        blocks[C].add(D)
        blocks[D].add(C)

    # print(friends)
    # print(blocks)

    # groups = {k: set(g) for k, g in uf.all_group_members().items()}
    people = [0] * (N + 1)

    for i in range(1, N+1):
        people[i] = uf.size(i)

    ans = [0] * N
    for i in range(1, N+1):
        total_count = people[i]
        parent = uf.find(i)
        for block in blocks[i]:
            block_parent = uf.find(block)
            if block_parent == parent:
                total_count -= 1
        ans[i-1] = total_count - len(friends[i]) - 1

    print(*ans)


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
# coding: utf-8


def solve(*args: str) -> str:
    n, m, k = map(int, args[0].split())

    friends = [set() for _ in range(n+1)]
    blocked = [set() for _ in range(n+1)]

    for a, b in map(str.split, args[1:1+m]):
        friends[int(a)].add(int(b))
        friends[int(b)].add(int(a))

    for c, d in map(str.split, args[1+m:1+m+k]):
        blocked[int(c)].add(int(d))
        blocked[int(d)].add(int(c))

    checked = set()

    ret = [0]*(n+1)
    for a in range(1, n+1):
        if a in checked:
            continue

        chain = set()

        stack = list(friends[a])
        while stack:
            b = stack.pop()
            if b in checked:
                continue

            checked.add(b)
            chain.add(b)
            stack.extend(friends[b])

        count = len(chain) - 1
        for i in chain:
            ret[i] += count - len(chain & (friends[i] | blocked[i]))

    return ' '.join(map(str, ret[1:]))


if __name__ == "__main__":
    print(solve(*(open(0).read().splitlines())))

Submission status: Accepted

Solution code:
import sys
#from io import StringIO
#import unittest

class UnionFind():
    # 作りたい要素数nで初期化
    # 使用するインスタンス変数の初期化
    def __init__(self, n):
        self.n = n
        # root[x]<0ならそのノードが根かつその値が木の要素数
        # rootノードでその木の要素数を記録する
        self.root = [-1]*(n+1)
        # 木をくっつける時にアンバランスにならないように調整する
        self.rnk = [0]*(n+1)

    # ノードxのrootノードを見つける
    def Find_Root(self, x):
        if(self.root[x] < 0):
            return x
        else:
            # ここで代入しておくことで、後の繰り返しを避ける
            self.root[x] = self.Find_Root(self.root[x])
            return self.root[x]
    # 木の併合、入力は併合したい各ノード
    def Unite(self, x, y):
        # 入力ノードのrootノードを見つける
        x = self.Find_Root(x)
        y = self.Find_Root(y)
        # すでに同じ木に属していた場合
        if(x == y):
            return 
        # 違う木に属していた場合rnkを見てくっつける方を決める
        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            # rnkが同じ（深さに差がない場合）は1増やす
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1
    # xとyが同じグループに属するか判断
    def isSameGroup(self, x, y):
        return self.Find_Root(x) == self.Find_Root(y)

    # ノードxが属する木のサイズを返す
    def Count(self, x):
        return -self.root[self.Find_Root(x)]

def resolve():
    int1 = lambda x: int(x) - 1
    readline=sys.stdin.readline

    n,m,k=map(int, readline().strip().split())

    uf = UnionFind(n)

    exc=[0]*n

    for i in range(m):
        a,b=map(int1, readline().strip().split())
        uf.Unite(a,b)
        exc[a]+=1
        exc[b]+=1
    
    for i in range(k):
        a,b=map(int1, readline().strip().split())
        if uf.isSameGroup(a,b):
            exc[a]+=1
            exc[b]+=1
    
    rescnt=[]

    for i in range(n):
        #ri=uf.Count(i)-1-exc[i]
        #rescnt.append(str(ri))
        if i==(n-1):
            print(uf.Count(i)-1-exc[i])
        else:
            print(uf.Count(i)-1-exc[i],end=" ")
    
        #print(" ".join(rescnt),end="")

resolve()

Submission status: Accepted

Solution code:
# -*- coding: utf-8 -*-
import bisect
import heapq
import math
import random
import sys
from collections import Counter, defaultdict, deque
from decimal import ROUND_CEILING, ROUND_HALF_UP, Decimal
from functools import lru_cache, reduce
from itertools import combinations, combinations_with_replacement, product, permutations
from operator import add, mul, sub

sys.setrecursionlimit(100000)
input = sys.stdin.readline
INF = 2**62-1

def read_int():
    return int(input())


def read_int_n():
    return list(map(int, input().split()))


def read_float():
    return float(input())


def read_float_n():
    return list(map(float, input().split()))


def read_str():
    return input().strip()


def read_str_n():
    return list(map(str, input().split()))


def error_print(*args):
    print(*args, file=sys.stderr)


def mt(f):
    import time

    def wrap(*args, **kwargs):
        s = time.time()
        ret = f(*args, **kwargs)
        e = time.time()

        error_print(e - s, 'sec')
        return ret

    return wrap


class UnionFind():
    def __init__(self):
        self.__table = {}
        self.__size = defaultdict(lambda: 1)
        self.__rank = defaultdict(lambda: 1)

    def __root(self, x):
        if x not in self.__table:
            self.__table[x] = x
        elif x != self.__table[x]:
            self.__table[x] = self.__root(self.__table[x])
        return self.__table[x]

    def root(self, x):
        return self.__table[x]

    def same(self, x, y):
        return self.__root(x) == self.__root(y)

    def union(self, x, y):
        x = self.__root(x)
        y = self.__root(y)
        if x == y:
            return

        if self.__rank[x] < self.__rank[y]:
            self.__table[x] = y
            self.__size[y] += self.__size[x]
        else:
            self.__table[y] = x
            self.__size[x] += self.__size[y]
            if self.__rank[x] == self.__rank[y]:
                self.__rank[x] += 1

    def size(self, x):
        return self.__size[self.__root(x)]

    def num_of_group(self):
        g = 0
        for k, v in self.__table.items():
            if k == v:
                g += 1
        return g

@mt
def slv(N, M, K, AB, CD):
    f = UnionFind()
    for a, b in AB:
        f.union(a, b)

    direct = defaultdict(int)
    for a, b in AB:
        direct[a] += 1
        direct[b] += 1
    block = defaultdict(set)
    for c, d in CD:
        block[c].add(d)
        block[d].add(c)


    ans = []
    for i in range(1, N+1):
        cand = f.size(i)
        for u in block[i]:
            if f.same(i, u):
                cand -= 1
        cand -= direct[i]
        cand -= 1
        ans.append(cand)
    return ans



def main():
    N, M, K = read_int_n()
    AB = [read_int_n() for _ in range(M)]
    CD = [read_int_n() for _ in range(K)]
    print(*slv(N, M, K, AB, CD))

if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
# coding: utf-8
from sys import setrecursionlimit


def dfs(node: int):
    if checked[node]:
        return

    checked[node] = True
    chain.add(node)
    for n in friends[node]:
        dfs(n)


def solve(*args: str) -> str:
    setrecursionlimit(2 * 10 ** 9)
    n, m, k = map(int, args[0].split())

    global friends
    friends = {i: set() for i in range(n+1)}
    blocked = {i: set() for i in range(n+1)}

    for a, b in map(str.split, args[1:1+m]):
        friends[int(a)].add(int(b))
        friends[int(b)].add(int(a))

    for c, d in map(str.split, args[1+m:1+m+k]):
        blocked[int(c)].add(int(d))
        blocked[int(d)].add(int(c))

    global checked
    checked = [False]*(n+1)

    ret = [0]*(n+1)
    for a in range(1, n+1):
        if checked[a]:
            continue

        global chain
        chain = set()
        dfs(a)
        count = len(chain) - 1
        for i in chain:
            ret[i] += count - len(chain & (friends[i] | blocked[i]))

    return ' '.join(map(str, ret[1:]))


if __name__ == "__main__":
    print(solve(*(open(0).read().splitlines())))

Submission status: Accepted

Solution code:
# -*- coding: utf-8 -*-
import bisect
import heapq
import math
import random
import sys
from collections import Counter, defaultdict, deque
from decimal import ROUND_CEILING, ROUND_HALF_UP, Decimal
from functools import lru_cache, reduce
from itertools import combinations, combinations_with_replacement, product, permutations
from operator import add, mul, sub

sys.setrecursionlimit(100000)
input = sys.stdin.readline
INF = 2**62-1

def read_int():
    return int(input())


def read_int_n():
    return list(map(int, input().split()))


def read_float():
    return float(input())


def read_float_n():
    return list(map(float, input().split()))


def read_str():
    return input().strip()


def read_str_n():
    return list(map(str, input().split()))


def error_print(*args):
    print(*args, file=sys.stderr)


def mt(f):
    import time

    def wrap(*args, **kwargs):
        s = time.time()
        ret = f(*args, **kwargs)
        e = time.time()

        error_print(e - s, 'sec')
        return ret

    return wrap


class UnionFind():
    def __init__(self):
        self.__table = {}
        self.__size = defaultdict(lambda: 1)

    def __root(self, x):
        if x not in self.__table:
            self.__table[x] = x
        elif x != self.__table[x]:
            self.__table[x] = self.__root(self.__table[x])
        return self.__table[x]

    def root(self, x):
        return self.__table[x]

    def same(self, x, y):
        return self.__root(x) == self.__root(y)

    def union(self, x, y):
        x = self.__root(x)
        y = self.__root(y)
        if self.size(x) > self.size(y):
            x, y = y, x
        if x != y:
            self.__size[y] += self.__size[x]
            self.__table[x] = y

    def size(self, x):
        return self.__size[self.__root(x)]

    def num_of_group(self):
        g = 0
        for k, v in self.__table.items():
            if k == v:
                g += 1
        return g

@mt
def slv(N, M, K, AB, CD):
    f = UnionFind()
    for a, b in AB:
        f.union(a, b)

    direct = defaultdict(int)
    for a, b in AB:
        direct[a] += 1
        direct[b] += 1
    block = defaultdict(set)
    for c, d in CD:
        block[c].add(d)
        block[d].add(c)


    ans = []
    for i in range(1, N+1):
        cand = f.size(i)
        for u in block[i]:
            if f.same(i, u):
                cand -= 1
        cand -= direct[i]
        cand -= 1
        ans.append(cand)
    return ans



def main():
    N, M, K = read_int_n()
    AB = [read_int_n() for _ in range(M)]
    CD = [read_int_n() for _ in range(K)]
    print(*slv(N, M, K, AB, CD))

if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
# -*- coding: utf-8 -*-
import bisect
import heapq
import math
import random
import sys
from collections import Counter, defaultdict, deque
from decimal import ROUND_CEILING, ROUND_HALF_UP, Decimal
from functools import lru_cache, reduce
from itertools import combinations, combinations_with_replacement, product, permutations
from operator import add, mul, sub

sys.setrecursionlimit(100000)
input = sys.stdin.readline
INF = 2**62-1

def read_int():
    return int(input())


def read_int_n():
    return list(map(int, input().split()))


def read_float():
    return float(input())


def read_float_n():
    return list(map(float, input().split()))


def read_str():
    return input().strip()


def read_str_n():
    return list(map(str, input().split()))


def error_print(*args):
    print(*args, file=sys.stderr)


def mt(f):
    import time

    def wrap(*args, **kwargs):
        s = time.time()
        ret = f(*args, **kwargs)
        e = time.time()

        error_print(e - s, 'sec')
        return ret

    return wrap


class UnionFind():
    def __init__(self):
        self.__table = {}
        self.__size = defaultdict(lambda: 1)

    def __root(self, x):
        if x not in self.__table:
            self.__table[x] = x
        elif x != self.__table[x]:
            self.__table[x] = self.__root(self.__table[x])
        return self.__table[x]

    def root(self, x):
        return self.__table[x]

    def same(self, x, y):
        return self.__root(x) == self.__root(y)

    def union(self, x, y):
        x = self.__root(x)
        y = self.__root(y)
        if self.size(x) < self.size(y):
            x, y = y, x
        if x != y:
            self.__size[y] += self.__size[x]
            self.__table[x] = y

    def size(self, x):
        return self.__size[self.__root(x)]

    def num_of_group(self):
        g = 0
        for k, v in self.__table.items():
            if k == v:
                g += 1
        return g

@mt
def slv(N, M, K, AB, CD):
    f = UnionFind()
    for a, b in AB:
        f.union(a, b)

    direct = defaultdict(int)
    for a, b in AB:
        direct[a] += 1
        direct[b] += 1
    block = defaultdict(set)
    for c, d in CD:
        block[c].add(d)
        block[d].add(c)


    ans = []
    for i in range(1, N+1):
        cand = f.size(i)
        for u in block[i]:
            if f.same(i, u):
                cand -= 1
        cand -= direct[i]
        cand -= 1
        ans.append(cand)
    return ans



def main():
    N, M, K = read_int_n()
    AB = [read_int_n() for _ in range(M)]
    CD = [read_int_n() for _ in range(K)]
    print(*slv(N, M, K, AB, CD))

if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
from sys import stdin
nii=lambda: map(int, stdin.readline().split())

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())


n,m,k=map(int,input().split())

tree_f=[[] for i in range(n+1)]
tree_g=[[] for i in range(n+1)]

uf=UnionFind(n+1)

for i in range(m):
  a,b=nii()
  tree_f[a].append(b)
  tree_f[b].append(a)
  uf.union(a,b)

for i in range(k):
  a,b=nii()
  if uf.find(a)==uf.find(b):
    tree_g[a].append(b)
    tree_g[b].append(a)

ans=[]
for i in range(n):
  i+=1
#  sst=list(set(tree_f[i]+tree_g[i]) & set(uf.members(i)))
#  cnt=len(sst)
  cnt=len(tree_f[i])+len(tree_g[i])
  ans.append(uf.size(i)-cnt-1)

print(*ans)

Submission status: Accepted

Solution code:
import sys
from io import StringIO
import unittest

class UnionFind():
    # 作りたい要素数nで初期化
    # 使用するインスタンス変数の初期化
    def __init__(self, n):
        self.n = n
        # root[x]<0ならそのノードが根かつその値が木の要素数
        # rootノードでその木の要素数を記録する
        self.root = [-1]*(n+1)
        # 木をくっつける時にアンバランスにならないように調整する
        self.rnk = [0]*(n+1)

    # ノードxのrootノードを見つける
    def Find_Root(self, x):
        if(self.root[x] < 0):
            return x
        else:
            # ここで代入しておくことで、後の繰り返しを避ける
            self.root[x] = self.Find_Root(self.root[x])
            return self.root[x]
    # 木の併合、入力は併合したい各ノード
    def Unite(self, x, y):
        # 入力ノードのrootノードを見つける
        x = self.Find_Root(x)
        y = self.Find_Root(y)
        # すでに同じ木に属していた場合
        if(x == y):
            return 
        # 違う木に属していた場合rnkを見てくっつける方を決める
        elif(self.rnk[x] > self.rnk[y]):
            self.root[x] += self.root[y]
            self.root[y] = x

        else:
            self.root[y] += self.root[x]
            self.root[x] = y
            # rnkが同じ（深さに差がない場合）は1増やす
            if(self.rnk[x] == self.rnk[y]):
                self.rnk[y] += 1
    # xとyが同じグループに属するか判断
    def isSameGroup(self, x, y):
        return self.Find_Root(x) == self.Find_Root(y)

    # ノードxが属する木のサイズを返す
    def Count(self, x):
        return -self.root[self.Find_Root(x)]

def resolve():
    n,m,k=map(int, sys.stdin.readline().strip().split())
    #list(map(int,input().strip().split()))

    uf = UnionFind(n)

    res=[[] for i in range(n)]
    frd=[0 for i in range(n)]
    blk=[0 for i in range(n)]

    for i in range(m):
        #a,b=list(map(int,input().strip().split()))
        a,b=map(int, sys.stdin.readline().strip().split())
        a-=1
        b-=1
        uf.Unite(a,b)
        frd[a]+=1
        frd[b]+=1
    
    for i in range(k):
        #a,b=list(map(int,input().strip().split()))
        a,b=map(int, sys.stdin.readline().strip().split())
        a-=1
        b-=1
        if uf.isSameGroup(a,b):
            blk[a]+=1
            blk[b]+=1
    
    rescnt=[]

    for i in range(n):
        ri=uf.Count(i)-1-blk[i]-frd[i]
        rescnt.append(str(ri))
        ##rescnt.append(str(n-uf.size(i)-len(blk[i])))
    
    print(" ".join(rescnt))

resolve()

Submission status: Accepted

Solution code:
class UnionFind:
    def __init__(self, n):
        self.par = list(range(n + 1))
        self.size = [1] * (n + 1)

    def root(self, x: int) -> int:
        if self.par[x] == x: return x
        self.par[x] = self.root(self.par[x])
        return self.par[x]

    def unite(self, x: int, y: int):
        root_x, root_y = self.root(x), self.root(y)
        if root_x != root_y:
            if self.size[root_x] < self.size[root_y]:
                root_x, root_y = root_y, root_x
            self.size[root_x] += self.size[root_y]
            self.par[root_y] = root_x

    def check(self, x: int, y: int) -> bool:
        root_x, root_y = self.root(x), self.root(y)
        return root_x == root_y


from collections import defaultdict
N, M, K = map(int, input().split())

u = UnionFind(N)

ABm = defaultdict(list)
for _ in range(M):
    a, b = map(int, input().split())
    ABm[a].append(b)
    ABm[b].append(a)
    u.unite(a, b)

CDk = defaultdict(list)
for _ in range(K):
    c, d = map(int, input().split())
    CDk[c].append(d)
    CDk[d].append(c)

ans = []
for i in range(1, N + 1):
    size = u.size[u.root(i)]
    block = 0
    for x in CDk[i]:
        if u.check(x, i): block += 1

    friends = len(ABm[i])
    res = size - block - friends - 1
    ans.append(str(res))

print(" ".join(ans))

Submission status: Accepted

Solution code:
# -*- coding: utf-8 -*-
import bisect
import heapq
import math
import random
import sys
from collections import Counter, defaultdict, deque
from decimal import ROUND_CEILING, ROUND_HALF_UP, Decimal
from functools import lru_cache, reduce
from itertools import combinations, combinations_with_replacement, product, permutations
from operator import add, mul, sub

sys.setrecursionlimit(100000)
input = sys.stdin.readline
INF = 2**62-1

def read_int():
    return int(input())


def read_int_n():
    return list(map(int, input().split()))


def read_float():
    return float(input())


def read_float_n():
    return list(map(float, input().split()))


def read_str():
    return input().strip()


def read_str_n():
    return list(map(str, input().split()))


def error_print(*args):
    print(*args, file=sys.stderr)


def mt(f):
    import time

    def wrap(*args, **kwargs):
        s = time.time()
        ret = f(*args, **kwargs)
        e = time.time()

        error_print(e - s, 'sec')
        return ret

    return wrap


class UnionFind():
    def __init__(self):
        self.__table = {}
        self.__size = defaultdict(lambda: 1)

    def __root(self, x):
        if x not in self.__table:
            self.__table[x] = x
        elif x != self.__table[x]:
            self.__table[x] = self.__root(self.__table[x])
        return self.__table[x]

    def root(self, x):
        return self.__table[x]

    def same(self, x, y):
        return self.__root(x) == self.__root(y)

    def union(self, x, y):
        x = self.__root(x)
        y = self.__root(y)
        if x != y:
            self.__size[y] += self.__size[x]
            self.__table[x] = y

    def size(self, x):
        return self.__size[self.__root(x)]

    def num_of_group(self):
        g = 0
        for k, v in self.__table.items():
            if k == v:
                g += 1
        return g

@mt
def slv(N, M, K, AB, CD):
    f = UnionFind()
    for a, b in AB:
        f.union(a, b)


    direct = defaultdict(int)
    for a, b in AB:
        direct[a] += 1
        direct[b] += 1
    block = defaultdict(set)
    for c, d in CD:
        block[c].add(d)
        block[d].add(c)


    ans = []
    for i in range(1, N+1):
        cand = f.size(i)
        for u in block[i]:
            if f.same(i, u):
                cand -= 1
        cand -= direct[i]
        cand -= 1
        ans.append(cand)
    return ans



def main():
    N, M, K = read_int_n()
    AB = [read_int_n() for _ in range(M)]
    CD = [read_int_n() for _ in range(K)]
    print(*slv(N, M, K, AB, CD))

if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
# -*- coding: utf-8 -*-
import bisect
import heapq
import math
import random
import sys
from collections import Counter, defaultdict, deque
from decimal import ROUND_CEILING, ROUND_HALF_UP, Decimal
from functools import lru_cache, reduce
from itertools import combinations, combinations_with_replacement, product, permutations
from operator import add, mul, sub

sys.setrecursionlimit(100000)
input = sys.stdin.readline
INF = 2**62-1

def read_int():
    return int(input())


def read_int_n():
    return list(map(int, input().split()))


def read_float():
    return float(input())


def read_float_n():
    return list(map(float, input().split()))


def read_str():
    return input().strip()


def read_str_n():
    return list(map(str, input().split()))


def error_print(*args):
    print(*args, file=sys.stderr)


def mt(f):
    import time

    def wrap(*args, **kwargs):
        s = time.time()
        ret = f(*args, **kwargs)
        e = time.time()

        error_print(e - s, 'sec')
        return ret

    return wrap


class UnionFind():
    def __init__(self):
        self.__table = {}
        self.__size = defaultdict(lambda: 1)

    def __root(self, x):
        if x not in self.__table:
            self.__table[x] = x
        elif x != self.__table[x]:
            self.__table[x] = self.__root(self.__table[x])
        return self.__table[x]

    def root(self, x):
        return self.__table[x]

    def same(self, x, y):
        return self.__root(x) == self.__root(y)

    def union(self, x, y):
        x = self.__root(x)
        y = self.__root(y)
        if x != y:
            self.__size[y] += self.__size[x]
            self.__table[x] = y

    def size(self, x):
        return self.__size[self.__root(x)]

    def num_of_group(self):
        g = 0
        for k, v in self.__table.items():
            if k == v:
                g += 1
        return g

@mt
def slv(N, M, K, AB, CD):
    g = defaultdict(set)
    for a, b in AB:
        g[a].add(b)
        g[b].add(a)

    def dfs(u):
        s = [u]
        done = set(s)
        while s:
            u = s.pop()
            for v in g[u]:
                if v not in done:
                    s.append(v)
                    done.add(v)
        return done

    group = dict()
    done = set()
    parent = [-1] * (N+1)
    for i in range(1, N+1):
        if i not in done:
            j = dfs(i)
            done |= j
            for k in j:
                parent[k] = i
            group[i] = j

    error_print('1')

    direct = defaultdict(int)
    for a, b in AB:
        direct[a] += 1
        direct[b] += 1
    block = defaultdict(set)
    for c, d in CD:
        block[c].add(d)
        block[d].add(c)

    error_print('2')

    ans = []
    for i in range(1, N+1):
        e = group[parent[i]]
        cand = len(group[parent[i]])
        for b in block[i]:
            if b in e:
                cand -= 1
        cand -= direct[i]
        cand -= 1
        ans.append(cand)
    error_print('3')
    return ans



def main():
    N, M, K = read_int_n()
    AB = [read_int_n() for _ in range(M)]
    CD = [read_int_n() for _ in range(K)]
    print(*slv(N, M, K, AB, CD))

    # N = 10**5
    # M = 10**5
    # K = 10**5
    # AB = [[random.randint(1, N), random.randint(1, N)] for _ in range(M)]
    # CD = [[random.randint(1, N), random.randint(1, N)] for _ in range(K)]
    # print(*slv(N, M, K, AB, CD))


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
import sys
read = sys.stdin.read
readline = sys.stdin.readline
readlines = sys.stdin.readlines


def main():
    N,M,K = map(int, readline().split())

    F = [[] for _ in range(N+1)]
    for _ in range(M):
        a,b = map(int, readline().split())
        F[a].append(b)
        F[b].append(a)
    
    B = [[] for _ in range(N+1)]
    for _ in range(K):
        c,d = map(int, readline().split())
        B[c].append(d)
        B[d].append(c)


    seen = [-1]*(N+1)
    group = 0
    def dfs(G, s):
        stack = [s]
        seen[s] = group
        n_connection = 1 
        
        while stack:
            u = stack.pop()
            for v in G[u]:
                if seen[v] == -1:
                    n_connection += 1
                    seen[v] = group
                    stack.append(v)
    
        return n_connection


    union = {}
    for i in range(1,N+1):
        if seen[i] == -1:
            n = dfs(F, i)
            union[group] = n
            group += 1
            
    ans = []
    for i in range(1,N+1):
        tmp = 0
        tmp += union[seen[i]] - 1
        tmp -= len(F[i])
        for j in B[i]:
            if seen[j] == seen[i]:
                tmp -= 1
        ans.append(tmp)
    
    print(" ".join(map(str, ans)))


if __name__ == "__main__":
    main()