ทางลัด

o58_oct_c1_bypass

ข้อนี้แท้จริงแล้วโจทย์ต้องการให้เราหาคู่เมือง uu และ vv ที่ จำนวนเมืองที่ต้องผ่าน uu ถึงจะไป vv ได้ คูณกับ จำนวนเมืองที่ต้องผ่าน vv ถึงจะไป uu ได้ มีค่ามากที่สุด

Key ของข้อนี้คือคู่เมือง uu และ vv ที่ดีที่สุดจะอยู่ห่างกัน 2 step เท่านั้น เนื่องจาก หากมันอยู่ห่างกันมากกว่านี้เราสามารถขยับ uu เข้าไปใกล้ขึ้นได้ และ คำตอบจะดีขึ้นเสมอ

เราจะแก้โจทย์นี้ในต้นไม้ที่ root ที่เมือง 11 โดยนิยามใหั sizeisize_i เป็น ขนาดของ subtree ของ ii

สำหรับเมือง xx ใดๆ เราจะสนใจแค่เมือง yy ที่มีทางเชื่อมกับ xx เท่านั้น โดย

  1. yy เป็นลูกของ xx: จำนวนเมืองที่ต้องผ่าน yy จะเท่ากับ sizeysize_y
  2. yy เป็นพ่อของ xx: จำนวนเมืองที่ต้องผ่าน yy จะเท่ากับ nsizexn - size_x

ในบรรดาเมือง yy เหล่านี้ เราจะสนใจแค่ค่าสองอันดับที่มากที่สุดและนำมาคูณกัน

Time-complexity: O(N)\mathcal{O}(N)

void solve(int u, int par) {
  sz[u] = 1;
  for(auto v : adj[u]) {
    if(v == par) continue;
    solve(v, u);
    sz[u] += sz[v];
  }
  
  int mx[2] = {-1, -1};
  for(auto v : adj[u]) {
    int val;
    if(v == par) val = n - sz[u];
    else val = sz[v];
    
    if(val > mx[0]) swap(mx[0], val);
    if(val > mx[1]) swap(mx[1], val);
  }
  
  if(mx[0] != -1 && mx[1] != -1) {
      ans = max(ans, (long long)mx[0] * mx[1]);
  }
}