🌲
【Python】木の直径
木の直径
木の単純パスの長さの最大値の事を、木の直径と言います。
例えば、以下のグラフであれば、
頂点1と4(または5)を繋ぐ単純パスが最も長いものであるので、このグラフの直径は3です。
O(N^2) の解法
頂点間のパスが最も長いものを見つければ良いので、BFSやDFS等を用いて、全ての頂点間の距離を求めてあげれば、その最大値が木の直径になります。ただし、これでは
O(N) の解法
木の直径を求めることは、
- 頂点1からの最短経路が最も長い頂点
を求める。u - 頂点
からの最短経路が最も長い頂点u を求める。v - 頂点
間の距離が木の直径となる。u, v
最短経路を求めるアルゴリズムは、ダイクストラ法などがありますが、今回は木であるため、わざわざダイクストラ法を使う必要はありません。(閉路が無いため)単純にDFSやBFSで、端の頂点まで見ていくだけで、
例題
与えられるグラフは木です。木であれば、任意の隣接していない頂点間を繋ぐ事で、必ずその辺を含む閉路が作れます。この問題は、木の直径を求めて、その頂点間を繋ぐ辺を追加することで、スコアを最大化することができます。
今回は、DFSを用いて解答します。
import sys
sys.setrecursionlimit(10**6)
N = int(input())
edges = [[] for _ in range(N)]
for _ in range(N-1):
a, b = map(int, input().split())
edges[a-1].append(b-1)
edges[b-1].append(a-1)
dist = [float('inf')] * N
dist[0] = 0
max_dist = {'node': -1, 'dist': -1}
def dfs(x, prev):
for y in edges[x]:
if y == prev:
continue
dist[y] = dist[x] + 1
if max_dist['dist'] < dist[y]:
max_dist['dist'] = dist[y]
max_dist['node'] = y
dfs(y, x)
dfs(0, -1)
dist = [float('inf')] * N
node = max_dist['node']
dist[node] = 0
max_dist = {'node': -1, 'dist': -1}
dfs(node, -1)
print(max_dist['dist'] + 1)
木には閉路が存在しないため、探索中に同じ頂点を通ることはありません。従って、まだ探索していない頂点を見つければ、その頂点に移動して貪欲に最短距離を更新していけば良いです。
参考
Discussion