hirohirohirohirosのブログ

地方国立大学に通う情報系学部4年

Atcoder ABC231 振り返り

 バーチャルで参加しました(221位).Union Findはいつかちゃんと実装しないとなと思っていたので今回これを使う問題が出てきて良かったです.

A - Water Pressure【AC】

 言われたことをそのまま実装するだけです.

D = int(input())
print(D/100)
B - Election【AC】

 辞書を使って投票人数をカウントします.keyが存在しないときsetdefaultを使うと簡単にkeyをvalueを設定できます.

S = int(input())
dic = {}

for _ in range(S):
    name = input()
    dic.setdefault(name, 0)
    dic[name] += 1

v = 0
for key, values in dic.items():
    if values > v:
        k = key
        v = values
print(k)
C - Counting 2【AC】

 二分探索を使います.二分探索はソートされた数列に対して,新しい数をソートを乱さないように挿入するには何番目に挿入すればいいかを計算量log nで求めてくれます.

import bisect
N, Q = map(int, input().split())
A = sorted([int(i) for i in input().split()])

for _ in range(Q):
    x = int(input())
    print(N-bisect.bisect_left(A, x))
D - Neighbors【AC】

 人がどう繋がっていたら直線じゃなくなるかを考えます.一つ目のパターンはとある人1人に対して3人以上繋がっていた場合です.f:id:hirohirohirohiros:20220213232423p:plain
これは隣接リストを使って要素が3つ以上あったら検出できます.
 二つ目のパターンは複数人でループしていた場合です.
f:id:hirohirohirohiros:20220213232641p:plain
これは隣接リストを見るだけでは検出できません.今回はUnion Findを使います.
 Union Findでは,あるノードとあるノードがいくつかのノードを経て繋がっているかどうかを高速で判定してくれます.あるノードとノードを繋げようとしたとき,既にそのノード達が繋がっていたら追加で辺を加えて繋げることになり,そこが閉路になります.これによって閉路を見つけることが出来ます.
 直線でなくなるパターンはこの二つなのでこれを見つけることが出来れば良いです.

N, M = map(int, input().split())
node = [[] for _ in range(N)]
par = [i for i in range(N)]
rank = [0]*(N)
ok = True

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

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

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

for _ in range(M):
    a,b = map(int, input().split())
    a, b = a-1, b-1
    node[a].append(b)
    node[b].append(a)
    if same(a, b):
        ok = False
    else:
        unite(a, b)
    
for i in range(N):
    if len(node[i]) >= 3:
        ok = False
        break
    
print("Yes" if ok else "No")