毎日格上の問題を倒すやつの36日目です。
問題リンク
問題概要
木が与えられるよ。
すべてのパス について、 と のLCAの最大値を類似度として、これを最小にする順列 を構築してね。
解法
明らかに、類似度を0にすることは不可能です。*1
そのため、類似度を1にすることを考えます。
パスグラフの場合、頂点の番号と逆向きに番号を振りたくなります。これを一般の場合にも応用します。
何がしたいかというと、「頂点の番号と遠いところに数字を書きたい」のです。この考え方をすると、以下のアルゴリズムに行きつきます。
- すべての葉に対して、番号をシャッフルしてつけたのち、葉を削除する*2
このようにしてうまくいくことは、帰納法により示せます。
提出コード
from collections import deque N=int(input()) tree=[set() for i in range(N)] for i in range(N-1): a,b=map(int,input().split()) tree[a-1].add(b-1) tree[b-1].add(a-1) one=deque() for i in range(N): if len(tree[i])==1: one.append((0,i)) cnt=0 ans=[-1]*N while len(one)>0: now=[] while len(one)>0 and one[0][0]==cnt: _,pos=one.popleft() for i in tree[pos]: tree[i].discard(pos) if len(tree[i])==1: one.append((cnt+1,i)) now.append(pos) for i in range(len(now)): ans[now[i]]=now[i-1]+1 cnt+=1 print(*ans)
Submission #46932286 - AtCoder Regular Contest 156
感想
nok0さんにいただいたけどおもしろかった
自薦https://t.co/hxwSge2vvF
— nok0 (@nok0_kyopro) 2023年10月25日
他薦https://t.co/m9JuXvS8ichttps://t.co/ZXXuFyT6rFhttps://t.co/HJDtFgT9Lk
自分が好きなやつ適当に投げます!