Official

B - Unique Nicknames Editorial by Nyaan


まずは「人 \(i\) にあだ名をつけることが可能か?」を判定する方法を考えてみましょう。
\(i\) につけられるあだ名 \(a_i\) の条件は次の \(2\) つです。

  • \(a_i = s_i\) または \(a_i = t_i\) が成り立つ。
  • \(1 \leq j \leq N, i \neq j\) を満たすすべての整数 \(j\) について \(a_i \neq s_j\) かつ \(a_i \neq t_j\) が成り立つ。

\(1\) つ目の条件から、\(a_i\) としてあり得るのは \(s_i\) または \(t_i\) のいずれかに限られます。よって、\(s_i\) または \(t_i\) の少なくとも一方が \(2\) つ目の条件を満たせば、人 \(i\) にあだ名をつけられることになります。
文字列 \(S\) が人 \(i\) のあだ名として条件を満たすかどうかは、 \(j\) を for-loop で走査して \(s_j,t_j\) と一致するものが存在するかを調べれば \(\mathrm{O}(N |s_i|)\) で判定できます。 (\(|S|\) は文字列 \(S\) の長さの意味。)

以上のアルゴリズムを実装すれば、「人 \(i\) にあだ名をつけることが可能かどうか?」を判定できます。これを人 \(1\)、人 \(2\), \(\dots\), 人 \(N\) すべての人に対して行えば、すべての人にあだ名をつけられるかを判定することができます。

計算量は \(\mathrm{O} \left(N^2 (\max(|s_i|)+\max(|t_i|)) \right)\) です。Python による実装例は次の通りです。

N = int(input())
s, t = [], []
for i in range(N):
  u, v = input().split()
  s.append(u)
  t.append(v)

for i in range(N):
  can_give_a_nickname = False
  for S in [s[i], t[i]]:
    s_ok = True
    for j in range(N):
      if i != j:
        if S == s[j] or S == t[j]:
          s_ok = False
    if s_ok == True:
      can_give_a_nickname = True
  if can_give_a_nickname == False:
    print("No")
    exit()

print("Yes")

posted:
last update: