Processing math: 100%

直径

2ノード間距離のうち最大のものを,そのグラフの直径という.ここでいう距離は,辺の重みは考慮しない.

木の直径は,2回のDFSで求めることができる.具体的には,任意のノードについて,最も遠いノードを求め,そのノードからまた最も遠いノードを求めると,後者の距離が木の直径である.以下に証明を示す.

証明

任意に選択したノードrから最も遠いノードxは直径の端点にならないと仮定する.直径(複数ありうる)の端点の集合をEとする.r->xパスが直径と最初に交わる点が存在すればそれをhとする.

  1. hが存在する時

r->h->xとなるパスが存在する.この時,hは直径上にあるので,hから最も遠いノードはEに属するノードである.ここで,rから最も遠いノードはxなのでxEに属する.これはxが直径の端点にならないことに⽭盾する.

  1. hが存在しない時

以下の式から,xを端点とする直径を構成することができるため,xが直径の端点にならないことに⽭盾する.

dist(r,x)dist(r,h)+maxuE(dist(h,u))

よってdist(h,x)+maxuE(dist(h,u))

以上から,背理法より,任意に選択したノードrから最も遠いノードxは直径の端点になる.したがって,任意のノードについて,最も遠いノードを求め,そのノードのから最も遠いノードまでの距離が直径となる.

コード

pair<int, int> dfs(int node, int parent, vector<vector<int>> &g) { pair<int, int> ret = {0, node}; for (int &e: g[node]) { if (e == parent) continue; pair<int, int> tmp = dfs(e, node, g); tmp.first++; chmax(ret, tmp); } return move(ret); } int diameter(vector<vector<int>> &g) { pair<int, int> d = dfs(0, -1, g); d = dfs(d.second, -1, g); return d.first; }