Official

D - Circumferences Editorial by en_translator


Consider a graph with \(N\) vertices corresponding to the \(N\) circles. For each integer pair \((i, j)\) such that \(1 \leq i \lt j \leq N\), add an undirected edge between Vertices \(i\) and \(j\) if and only if the \(i\)-th circle (which we simply call Circle \(i\)) and Circle \(j\) intersect.

In order to solve this problem, it is sufficient to construct the graph above, find a circle (which we denote by Circle \(S\)) that contains the starting point \((s_x, s_y)\) on its circumference and a circle (which we denote by Circle \(T\)) that contains the destination point \((t_x, t_y)\) on its circumference, and determine if it is possible to reach from Vertex \(S\) to Vertex \(T\) on the graph.

First, we consider how to construct such a graph. In order to do so, we need to determine if Circles \(i\) and \(j\) intersect. Circles \(i\) and \(j\) do not intersect if and only if one of the following two patterns applies:

  • If one of the circles is in the interior of the other circle, that is, \((x_i - x_j)^2 + (y_i - y_j)^2 \lt (r_i - r_j)^2\)

  • If one of the circles lies outside the other, that is, \((x_i - x_j)^2 + (y_i - y_j)^2 \gt (r_i + r_j)^2\)

Since we can check if two given circles satisfies one of the conditions above in an \(\mathrm{O}(1)\) time, the desired graph can be constructed in a total of \(\mathrm{O}(N^2)\) by checking for each integer pair \((i, j)\) such that \(1 \leq i \lt j \leq N\) if Circle \(i\) and \(j\) intersect.

Also, in order to find the circle \(S\) that contains the starting point \((s_x, s_y)\) on its circumference, it is sufficient to find \(i\) such that

\[ (x_i - s_x)^2 + (y_i - s_y)^2 = r_i^2, \tag{1} \]

satisfying the necessary and sufficient condition that point \((s_x, s_y)\) is contained in its circumference. This can be done in a total of \(\mathrm{O}(N)\) time by checking for each \(i = 1, 2, \ldots, N\) if (1) is satisfied. The circle \(T\) that contains \((t_x, t_y)\) on its circumference can be found in the same way.

One can determine if one can reach from Vertex \(S\) to Vertex \(T\) on the constructed graph with a searching algorithm on a graph (like Depth-First Search) in a total of \(\mathrm{O}(N^2)\) time.

Therefore, the problem can be solved in a total of \(\mathrm{O}(N^2)\) time.

The following is a sample code for this problem in C++ language.

#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;

int n;
ll sx, sy, tx, ty;
ll x[3005], y[3005], r[3005];
vector<int> G[3005];

int S, T;
bool used[3005];

bool dfs(int v)
{
  used[v] = true;
  if(v == T) return true;
  for(auto u : G[v]){
    if(used[u]) continue;
    if(dfs(u)) return true;
  }
  return false;
}

int main(void)
{
  cin >> n;
  cin >> sx >> sy >> tx >> ty;
  for(int i = 1; i <= n; i++) cin >> x[i] >> y[i] >> r[i];

  for(int i = 1; i <= n; i++){
    for(int j = i+1; j <= n; j++){
      ll d = (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]);
      if(d > (r[i]+r[j])*(r[i]+r[j]) || d < (r[i]-r[j])*(r[i]-r[j])) continue;
      G[i].push_back(j), G[j].push_back(i);
    }
  }

  for(int i = 1; i <= n; i++){
    if((x[i]-sx)*(x[i]-sx) + (y[i]-sy)*(y[i]-sy) == r[i]*r[i]) S = i;
    if((x[i]-tx)*(x[i]-tx) + (y[i]-ty)*(y[i]-ty) == r[i]*r[i]) T = i;
  }

  if(dfs(S)) cout << "Yes" << endl;
  else cout << "No" << endl;

  return 0;
}

posted:
last update: