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:
# D - Friend Suggestions
from collections import Counter
N,M,K = map(int,input().split())
AB = [tuple(map(int,input().split())) for i in range(M)]
CD = [tuple(map(int,input().split())) for i in range(K)]

class UnionFind:
    def __init__(self,N):
        self.parent = [i for i in range(N)]
        self.rank = [0] * N
        self.count = 0
    def root(self,a):
        if self.parent[a] == a:
            return a
        else:
            self.parent[a] = self.root(self.parent[a])
            return self.parent[a]
    def is_same(self,a,b):
        return self.root(a) == self.root(b)
    def unite(self,a,b):
        ra = self.root(a)
        rb = self.root(b)
        if ra == rb: return
        if self.rank[ra] < self.rank[rb]:
            self.parent[ra] = rb
        else:
            self.parent[rb] = ra
            if self.rank[ra] == self.rank[rb]: self.rank[ra] += 1
        self.count += 1

blocks = [[] for _ in range(N)]
for c,d in CD:
    c,d = c-1,d-1
    blocks[c].append(d)
    blocks[d].append(c)

friends = [0] * N
uf = UnionFind(N)
for a,b in AB:
    a,b = a-1,b-1
    friends[a] += 1
    friends[b] += 1
    if uf.is_same(a,b): continue
    uf.unite(a,b)
for i in range(N):
    uf.root(i)

ctr = Counter()
for i in range(N):
    r = uf.root(i)
    ctr[r] += 1

ans = []
for i in range(N):
    tmp = ctr[uf.root(i)] - 1 - friends[i]
    for b in blocks[i]:
        if uf.is_same(i,b):
            tmp -= 1
    ans.append(tmp)
print(*ans)

Submission status: Accepted

Solution code:
import sys
sys.setrecursionlimit(10**5)
N,M,K = list(map(int,input().split(' ')))

friend_list = [0]*(N+1)
bad_list = [0]*(N+1)
group = {}

parent = [i for i in range(N+1)]
rank = [0]*(N+1)

def union(x,y):
    x = find(x)
    y = find(y)
    if x==y:
        return
    if rank[x]<rank[y]:
        parent[x]=y
    else:
        parent[y]=x
        if rank[x]==rank[y]:
            rank[x]+=1

def find(x):
    if parent[x] == x:
        return x
    else:
        parent[x]= find(parent[x])
        return parent[x]





for i in range(M):
    A,B = list(map(int,input().split(' ')))
    friend_list[A]+=1
    friend_list[B]+=1
    
    union(A,B)

for i in range(1,N+1):
    oya = find(i)
    if oya in group:
        group[oya] = group[oya]+1
    else:
        group[oya]=1

for i in range(K):
    A,B = list(map(int,input().split(' ')))
    if find(A)==find(B):
        bad_list[A]+=1
        bad_list[B]+=1


kouho = [0]*N

for i in range(1,N+1):
    oya = find(i)
    abc = group[oya]-friend_list[i]-bad_list[i]-1
    kouho[i-1] = abc

for k in kouho:
    print(k,end=" ")
print()

Submission status: Accepted

Solution code:
import sys
sys.setrecursionlimit(10**5)
N,M,K = list(map(int,input().split(' ')))

friend_list = [0]*(N+1)
bad_list = [0]*(N+1)
group = {}

parent = [i for i in range(N+1)]
rank = [0]*(N+1)

def union(x,y):
    x = find(x)
    y = find(y)
    if x==y:
        return
    if rank[x]<rank[y]:
        parent[x]=y
    else:
        parent[y]=x
        if rank[x]==rank[y]:
            rank[x]+=1

def find(x):
    if parent[x] == x:
        return x
    else:
        parent[x]= find(parent[x])
        return parent[x]





for i in range(M):
    A,B = list(map(int,input().split(' ')))
    friend_list[A]+=1
    friend_list[B]+=1
    
    union(A,B)

for i in range(1,N+1):
    oya = find(i)
    parent[i] = oya
    #print(oya)
    if oya in group:
        group[oya] = group[oya]+1
    else:
        group[oya]=1

for i in range(K):
    A,B = list(map(int,input().split(' ')))
    if find(A)==find(B):
        bad_list[A]+=1
        bad_list[B]+=1
    
    #union(A,B)



#print(parent)
#print('parent')

#print('friend')
#print(friend_list)
#print('bad')
#print(bad_list) 
#print(group)

kouho = [0]*N

for i in range(1,N+1):
    oya = find(i)
    abc = group[oya]-friend_list[i]-bad_list[i]-1
    kouho[i-1] = abc

for k in kouho:
    print(k,end=" ")
print()

#print(parent)

Submission status: Accepted

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

# 0-indexed
class UnionFind:
  N=0
  parent=None
  size=None
  def __init__(self,N):
    self.N=N
    self.parent=[i for i in range(self.N)]
    self.size=[1]*self.N
    
  def root(self,x):
    while x!=self.parent[x]:
      self.parent[x]=self.parent[self.parent[x]]
      x=self.parent[x]
    return x
  
  def same(self,x,y):
    return self.root(x)==self.root(y)
  
  def unite(self,x,y):
    x=self.root(x)
    y=self.root(y)
    if x==y:
      return
    if self.size[x]>self.size[y]:
      # 大きい方にくっつける
      self.parent[y]=x
      self.size[x]+=self.size[y]
    else:
      self.parent[x]=y
      self.size[y]+=self.size[x]
      
  def get_group_size(self,x):
    return self.size[self.root(x)]
  
  def get_roots(self):
    r=set()
    for i in range(self.N):
      r.add(root(i))
    return r
  
  def show_parent(self):
    print(self.parent)
    
  def show_size(self):
    print(self.size)
    
N,M,K=map(int,readline().split())
UF=UnionFind(N)
friends=[0]*N
for i in range(M):
  a,b=map(int,readline().split())
  UF.unite(a-1,b-1)
  friends[a-1]+=1
  friends[b-1]+=1

from collections import defaultdict
block=defaultdict(set)
for i in range(K):
  c,d=map(int,readline().split())
  block[c-1].add(d-1)
  block[d-1].add(c-1)

ans=[0]*N
for i in range(N):
  ans[i]=UF.get_group_size(i)-friends[i]-1
  for b in block[i]:
    if UF.same(i,b):
      ans[i]-=1
  if ans[i]<0:
    ans[i]=0
print(*ans)

Submission status: Accepted

Solution code:
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)    

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

uf = UnionFind(n)
A = {i:[] for i in range(n)}
for i in range(m):
  a,b = map(int,input().split())
  a,b = a-1,b-1
  A[a].append(b)
  A[b].append(a)
  uf.union(a,b)
  
C = {i:[] for i in range(n)}
for i in range(k):
  c,d = map(int,input().split())  
  c,d = c-1,d-1
  if uf.same(c,d):
    C[c].append(d)
    C[d].append(c)
  
ans = [0]*n
for i in range(n):    
  ans[i] = uf.size(i) - len(A[i]) - len(C[i]) - 1  
print(*ans)

Submission status: Accepted

Solution code:
import sys
sys.setrecursionlimit(2147483647)
input = sys.stdin.readline

N, M, K = map(int, input().split())
friends = {i: set() for i in range(N)}
blocks = {i: set() for i in range(N)}

for _ in range(M):
    a, b = map(int, input().split())
    friends[a-1].add(b-1)
    friends[b-1].add(a-1)

for _ in range(K):
    a, b = map(int, input().split())
    blocks[a-1].add(b-1)
    blocks[b-1].add(a-1)

counts = [0] * N
seen = [False] * N
def dfs(v):
    if seen[v] == True:
        return
    seen[v] = True
    for node in friends[v]:
        c.add(node)
        dfs(node)
 
for v in range(N):
    if seen[v] == True:
        continue
    c = set()
    dfs(v)
    l = len(c)
    for i in c:
        counts[i] = l - 1
        counts[i] -= len(c & friends[i])
        counts[i] -= len(c & blocks[i])
print(' '.join(map(str, counts)))

Submission status: Accepted

Solution code:
class Unionfind:

    def __init__(self,n):
        self.uf = [-1]*n

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

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

    def union(self,x,y):
        x = self.find(x)
        y = self.find(y)
        if x == y:
            return False
        if self.uf[x] > self.uf[y]:
            x,y = y,x
        self.uf[x] += self.uf[y]
        self.uf[y] = x
        return True

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

n,m,k = map(int,input().split())
un = Unionfind(n)
fre = [1]*n
for i in range(m):
    a,b = map(int,input().split())
    a -= 1
    b -= 1
    un.union(a,b)
    fre[a] += 1
    fre[b] += 1

ans = [un.size(i)-fre[i] for i in range(n)]

for i in range(k):
    a,b = map(int,input().split())
    a -= 1
    b -= 1
    if un.same(a,b):
        ans[a] -= 1
        ans[b] -= 1
print(*ans)

Submission status: Accepted

Solution code:
#!/usr/bin/env python3
import sys
sys.setrecursionlimit(10000000)
INF = 1<<32


# refered to
# rank : http://at274.hatenablog.com/entry/2018/02/02/173000
# size : abc120 kaisetsu
class UnionFind:
    def __init__(self, n):
        # par = Parent Number or NoV
        self.par = [-1] * (n+1)
        # rank = Tree Height
        self.rank = [0] * (n+1)
    
    # Returns the number of sets to which x belongs
    def size(self, x):
        return -1*self.par[self.find(x)]
    
    def size_list(self):
        return [x*(-1) for x in self.par[1:] if x < 0]

    # Returns number if root
    def find(self, x):
        if(self.par[x] < 1):
            return x
        self.par[x] = self.find(self.par[x])
        return self.par[x]

    # Are the parents of x and y the same?
    def same_check(self, x, y):
        return self.find(x) == self.find(y)

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

        # Already x connect to y
        if(x == y):
            return False

        # Reconnect
        if(self.size(x) < self.size(y)):
            x,y = y,x
        
        # update x size
        self.par[x] += self.par[y]
        # set parent number of y to x
        self.par[y] = x

        return True 
    
    def root_nodes(self):
        return len([i for i in self.par[1:] if i <= -1])
    
    

def solve(N: int, M: int, K: int, A: "List[int]", B: "List[int]", C: "List[int]", D: "List[int]"):
    """graph.input.linkedlist
        input: u[]:start, v[]:end
        output:g[][]
    """
    uf = UnionFind(N)

    g = [[] for i in range(N+1)]
    for i in range(M):
        g[A[i]].append(B[i])
        g[B[i]].append(A[i])
    
    g_b = [[] for i in range(N+1)]
    for i in range(K):
        g_b[C[i]].append(D[i])
        g_b[D[i]].append(C[i])
    

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

    ans = []
    for i in range(1, N+1):
        ans.append(uf.size(i)-1 - len(g[i]) - len([x for x in g_b[i] if uf.same_check(i, x) == True]))
        
    print(' '.join(map(str, ans)))
    
    return



def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    M = int(next(tokens))  # type: int
    K = int(next(tokens))  # type: int
    A = [int()] * (M)  # type: "List[int]"
    B = [int()] * (M)  # type: "List[int]"
    for i in range(M):
        A[i] = int(next(tokens))
        B[i] = int(next(tokens))
    C = [int()] * (K)  # type: "List[int]"
    D = [int()] * (K)  # type: "List[int]"
    for i in range(K):
        C[i] = int(next(tokens))
        D[i] = int(next(tokens))
    solve(N, M, K, A, B, C, D)

if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
#!/usr/bin/env python3
import sys
sys.setrecursionlimit(10000000)
INF = 1<<32


# refered to
# rank : http://at274.hatenablog.com/entry/2018/02/02/173000
# size : abc120 kaisetsu
class UnionFind:
    def __init__(self, n):
        # par = Parent Number or NoV
        self.par = [-1] * (n+1)
        # rank = Tree Height
        self.rank = [0] * (n+1)
    
    # Returns the number of sets to which x belongs
    def size(self, x):
        return -1*self.par[self.find(x)]
    
    def size_list(self):
        return [x*(-1) for x in self.par[1:] if x < 0]

    # Returns number if root
    def find(self, x):
        if(self.par[x] < 1):
            return x
        self.par[x] = self.find(self.par[x])
        return self.par[x]

    # Are the parents of x and y the same?
    def same_check(self, x, y):
        return self.find(x) == self.find(y)

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

        # Already x connect to y
        if(x == y):
            return False

        # Reconnect
        if(self.size(x) < self.size(y)):
            x,y = y,x
        
        # update x size
        self.par[x] += self.par[y]
        # set parent number of y to x
        self.par[y] = x

        return True 
    
    def root_nodes(self):
        return len([i for i in self.par[1:] if i <= -1])
    
    

def solve(N: int, M: int, K: int, A: "List[int]", B: "List[int]", C: "List[int]", D: "List[int]"):
    """graph.input.linkedlist
        input: u[]:start, v[]:end
        output:g[][]
    """
    uf = UnionFind(N)

    g = [[] for i in range(N+1)]
    for i in range(M):
        g[A[i]].append(B[i])
        g[B[i]].append(A[i])
    
    g_b = [[] for i in range(N+1)]
    for i in range(K):
        g_b[C[i]].append(D[i])
        g_b[D[i]].append(C[i])
    

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

    # for i in range(1, N+1):
    #     print(i, uf.size(i), g[i])

    # 同じ根だったらスキップする
    # ans = [ uf.size(i)-1 - len(g[i])  for i in range(1, N+1)]
    ans = []
    for i in range(1, N+1):
        # print("after: ", i, uf.size(i)-1, len(g[i]), g_b[i], [uf.same_check(i, x) for x in g_b[i]])
        ans.append(uf.size(i)-1 - len(g[i]) - len([x for x in g_b[i] if uf.same_check(i, x) == True]))
        
    print(' '.join(map(str, ans)))
    
    return



def main():
    def iterate_tokens():
        for line in sys.stdin:
            for word in line.split():
                yield word
    tokens = iterate_tokens()
    N = int(next(tokens))  # type: int
    M = int(next(tokens))  # type: int
    K = int(next(tokens))  # type: int
    A = [int()] * (M)  # type: "List[int]"
    B = [int()] * (M)  # type: "List[int]"
    for i in range(M):
        A[i] = int(next(tokens))
        B[i] = int(next(tokens))
    C = [int()] * (K)  # type: "List[int]"
    D = [int()] * (K)  # type: "List[int]"
    for i in range(K):
        C[i] = int(next(tokens))
        D[i] = int(next(tokens))
    solve(N, M, K, A, B, C, D)

if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
#!/usr/bin/env python3
class UnionFind():
    def __init__(self, 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]
            #return self.find(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
n,m,k = map(int,input().split())
uf = UnionFind(n)
#初期化したら友達関係を受け取ってufを形成していく union
friend = [0]*n
# 友達が何人いるかも必要
for i in range(m):
    a,b = map(int,input().split())
    friend[a-1] += 1
    friend[b-1] += 1
    uf.union(a-1,b-1)
# uf が完成したら,c,d を受け取り、parentの値が同じならblock[c],bloc[d]+=1をする
block = [0]*n
for j in range(k):
    c,d = map(int,input().split())
    if uf.find(c-1) == uf.find(d-1):
        block[c-1]+=1
        block[d-1]+=1
"""
print(uf.parents)
print(block)
print(friend)"""
for i in range(n):
    #print(abs(uf.parents[uf.find(i)]),":",i)
    print(abs(uf.parents[uf.find(i)]) - 1 - friend[i] - block[i],end=" ")

Submission status: Accepted

Solution code:
import sys
from bisect import bisect_left,bisect_right,insort
input = sys.stdin.readline
class UnionFind():
    def __init__(self,n):
        self.n=n
        self.parent=list(range(n+1))
        self.size=[1]*(n+1)
    def find(self,x):
    #根を探す。
    #別なグループ間をつなげた場合は、つなげた先の根に書き換える。
        if self.parent[x]==x:
            return x
        else:
            self.parent[x]=self.find(self.parent[x])
            return self.parent[x]
    def unite(self,x,y):
    #二つのグループをつなげる
    #大きいほうに小さいほうをつなげる。
        x=self.find(x)
        y=self.find(y)
        if x==y:
            return
        else:
            if self.size[x]>=self.size[y]:
                self.parent[y]=x
                self.size[x]+=self.size[y]
            else:
                self.parent[x]=y
                self.size[y]+=self.size[x]
    def cnt(self,x):
    #サイズの取得
        return self.size[self.find(x)]

def main():
    n,m,k=map(int,input().split())
    u=UnionFind(n)
    ans=[0]*(n+1)
    for i in range(m):
        a,b=map(int,input().split())
        ans[a]-=1
        ans[b]-=1
        u.unite(a,b)
    for i in range(k):
        a,b=map(int,input().split())
        if u.find(a)==u.find(b):
            ans[a]-=1
            ans[b]-=1
    for i in range(1,n+1):
        ans[i]+=u.cnt(i)-1
    print(" ".join(map(str,ans[1:])))

if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
#!/usr/bin/env python3
class UnionFind():
    def __init__(self, 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
n,m,k = map(int,input().split())
uf = UnionFind(n)
#初期化したら友達関係を受け取ってufを形成していく union
friend = [0]*n
# 友達が何人いるかも必要
for i in range(m):
    a,b = map(int,input().split())
    friend[a-1] += 1
    friend[b-1] += 1
    uf.union(a-1,b-1)
# uf が完成したら,c,d を受け取り、parentの値が同じならblock[c],bloc[d]+=1をする
block = [0]*n
for j in range(k):
    c,d = map(int,input().split())
    if uf.find(c-1) == uf.find(d-1):
        block[c-1]+=1
        block[d-1]+=1
"""
print(uf.parents)
print(block)
print(friend)"""
for i in range(n):
    #print(abs(uf.parents[uf.find(i)]),":",i)
    print(abs(uf.parents[uf.find(i)]) - 1 - friend[i] - block[i],end=" ")

Submission status: Accepted

Solution code:
# Union-Find木（サイズ付き）
class UnionFind():
    # 初めは全ての頂点が別々の木の根
    def __init__(self, n):  # n要素で初期化
        self.parent = [None] * n # 親
        self.rank = [None] * n   # 木の深さ
        self._size = [1] * n # 要素が属する集合の大きさ（根の要素のみ参照すること）
        for i in range(n):
            self.parent[i] = i
            self.rank[i] = 0

    # 木の根を求める
    def root_of(self, x):
        children = [x]
        while self.parent[x] != x:
            x = self.parent[x]
            children.append(x)

        for ch in children:
            self.parent[ch] = x

        return x

    # xとyの属する集合を併合
    def unite(self, x, y):
        rx = self.root_of(x)
        ry = self.root_of(y)
        if rx == ry:
            return
        if self.rank[rx] < self.rank[ry]: # ランクの小さい木から大きい木の根に辺を張る
            self.parent[rx] = ry  # rxをryの子とする
            self._size[ry] += self._size[rx]
        else:
            self.parent[ry] = rx
            self._size[rx] += self._size[ry]
            if self.rank[rx] == self.rank[ry]:
                self.rank[rx] += 1

    # 同じ集合に属するかどうか
    def is_same(self, x, y):
        return self.root_of(x) == self.root_of(y)

    # 頂点xが属する集合のサイズ
    def size(self, x):
        return self._size[self.root_of(x)]


# 入力
N, M, K = [int(x) for x in input().split()]

Ef = [[int(x) - 1 for x in input().split()] for _ in range(M)]
Eb = [[int(x) - 1 for x in input().split()] for _ in range(K)]

ans = [0] * N
uf = UnionFind(N)
for i in range(M):
    uf.unite(Ef[i][0], Ef[i][1])
    ans[Ef[i][0]] -= 1  # すでに友達なら友達候補ではない
    ans[Ef[i][1]] -= 1

for i in range(K):
    if uf.is_same(Eb[i][0], Eb[i][1]):
        ans[Eb[i][0]] -= 1  # ブロックしているなら友達候補ではない
        ans[Eb[i][1]] -= 1

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

print(" ".join([str(i) for i in ans]))

Submission status: Accepted

Solution code:
class union_find():
    __slots__ = ["par", "rank", "size"]
    def __init__(self, n):
        self.par = [i for i in range(n + 1)]
        self.rank = [1 for i in range(n + 1)]
        self.size = [1 for i in range(n + 1)]

    def find(self, c):
        if self.par[c] == c:
            return c

        ret = self.find(self.par[c])
        self.par[c] = ret
        return ret

    def union(self, x, y):

        xr = self.find(x)
        yr = self.find(y)
        if xr == yr:
            return

        if self.rank[yr] > self.rank[xr]:
            self.par[xr] = yr
            self.size[yr] += self.size[xr]
        else:
            self.par[yr] = xr
            self.size[xr] += self.size[yr]
            if self.rank[xr] == self.rank[yr]:
                self.rank[xr] += 1

    def size_belong(self, i):
        return self.size[self.find(i)]

    def mass_size(self):
        return [i == v for i, v in enumerate(self.par)].count(True) - 1

    def show(self):
        print('parent', self.par[1:])
        print('rank', self.rank[1:])

def main():
    from collections import defaultdict

    dicf = defaultdict(lambda :[])
    dicb = defaultdict(lambda :[])

    N, M, K = map(int, input().split())

    uf = union_find(N)
    for i in range(M):
        a, b = map(int, input().split())
        dicf[a].append(b)
        dicf[b].append(a)
        if a > b:
            a, b = b, a
        uf.union(a, b)

    for i in range(K):
        c, d = map(int, input().split())
        dicb[c].append(d)
        dicb[d].append(c)

    ans = []
    for i in range(1, N + 1):
        x = uf.size_belong(i) - len(dicf[i]) - 1
        m = 0
        for b in dicb[i]:
            if uf.find(b) == uf.find(i):
                m += 1

        ans.append(x - m)


    print(' '.join(map(str, ans)))




if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
def main():
    from collections import deque
    import sys
    input = sys.stdin.readline

    N, M, K = map(int, input().split())

    g = tuple(set() for _ in range(N))
    direct_friend = [0] * N
    for _ in range(M):
        a, b = (int(x) - 1 for x in input().split())

        g[a].add(b)
        g[b].add(a)

        direct_friend[a] += 1
        direct_friend[b] += 1

    bk = tuple(set() for _ in range(N))
    for _ in range(K):
        c, d = (int(x) - 1 for x in input().split())
        bk[c].add(d)
        bk[d].add(c)

    dq = deque()
    checked = [-1] * N
    for v in range(N):
        if ~checked[v]: continue

        dq.append(v)  # v
        checked[v] = v
        root = v
        while dq:
            v = dq.pop()
            for u in g[v]:
                if ~checked[u]: continue
                checked[u] = root
                dq.append(u)

    ctr = [0] * N
    for v in range(N):
        root = checked[v]
        ctr[root] += 1

    ret = []
    for v in range(N):
        root = checked[v]
        t = ctr[root] - direct_friend[v] - 1 - sum(checked[u] == root for u in bk[v])
        ret.append(t)

    print(*ret)


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
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 unite(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 isSame(self, x, y):
        return self.find(x) == self.find(y)

def solve():
    N, M, K = map(int, input().split())
    dame = [set() for i in range(N)]
    uf = UnionFind(N)

    for i in range(M):
        a, b = map(lambda x: int(x)-1, input().split())
        
        dame[a].add(b)
        dame[b].add(a)
        uf.unite(a,b)
    
    for i in range(K):
        c, d = map(lambda x: int(x)-1, input().split())
        if not uf.isSame(c, d):
            continue
        dame[c].add(d)
        dame[d].add(c)
    
    ans = []
    for i in range(N):
        mem = uf.size(i) - 1
        mem -= len(dame[i])
        ans.append(mem)
    
    print(*ans, sep=' ')

if __name__ == '__main__':
    solve()

Submission status: Accepted

Solution code:
def main():
    from collections import defaultdict, deque
    import sys
    input = sys.stdin.readline

    N, M, K = map(int, input().split())

    g = tuple(set() for _ in range(N))
    direct_friend = [0] * N
    for _ in range(M):
        a, b = (int(x) - 1 for x in input().split())

        g[a].add(b)
        g[b].add(a)

        direct_friend[a] += 1
        direct_friend[b] += 1

    bk = tuple(set() for _ in range(N))
    for _ in range(K):
        c, d = (int(x) - 1 for x in input().split())
        bk[c].add(d)
        bk[d].add(c)

    dq = deque()
    checked = [-1] * N
    for v in range(N):
        if ~checked[v]: continue

        dq.append(v)  # v
        checked[v] = v
        root = v
        while dq:
            v = dq.pop()
            for u in g[v]:
                if ~checked[u]: continue
                checked[u] = root
                dq.append(u)

    ctr = defaultdict(int)
    for v in range(N):
        root = checked[v]
        ctr[root] += 1

    ret = []
    for v in range(N):
        root = checked[v]
        t = ctr[root] - direct_friend[v] - 1 - sum(checked[u] == root for u in bk[v])
        ret.append(t)

    print(*ret)


if __name__ == '__main__':
    main()

Submission status: Accepted

Solution code:
def main():
    from collections import defaultdict, deque
    import sys
    input = sys.stdin.readline

    N, M, K = map(int, input().split())

    g = tuple(set() for _ in range(N))
    direct_friend = [0] * N
    for _ in range(M):
        a, b = (int(x) - 1 for x in input().split())

        g[a].add(b)
        g[b].add(a)

        direct_friend[a] += 1
        direct_friend[b] += 1

    bk = tuple(set() for _ in range(N))
    for _ in range(K):
        c, d = (int(x) - 1 for x in input().split())
        bk[c].add(d)
        bk[d].add(c)

    dq = deque()
    checked = [-1] * N
    for v in range(N):
        if ~checked[v]:
            continue

        dq.append((v, v))  # v,root
        checked[v] = v
        while dq:
            v, root = dq.pop()
            for u in g[v]:
                if ~checked[u]:
                    continue
                checked[u] = root
                dq.append((u, root))

    ctr = defaultdict(int)
    for v in range(N):
        root = checked[v]
        ctr[root] += 1

    ret = []
    for v in range(N):
        root = checked[v]
        t = ctr[root] - direct_friend[v] - 1
        for u in bk[v]:
            if checked[u] == root:
                # 同じ連結成分に属するがブロック関係
                # for二重なので間に合わないと思っていたが総数K<=10**5で間に合う
                t -= 1
        ret.append(t)

    print(*ret)


if __name__ == '__main__':
    main()