Go: package main

import (
	"bufio"
	"os"
	"strconv"
	"strings"
	"math"
	"fmt"
)

var scanner = bufio.NewScanner(os.Stdin)

func main() {
	dd := make([][]int, 1000)
	for i := range dd {
		dd[i] = make([]int, 1000)
	}
	num := make([]int,1000)
	inv := make([]int, 1001)
	x := make([]int, 1000)
	y := make([]int, 1000)
	vv := make([]int, 1000)
	nowt := make([]float64, 1000)
	rev := make([]int, 1000)
	for scanner.Scan() {
		n, _ := strconv.Atoi(scanner.Text())
		if n == 0 {
			break
		}
		for i := 0; i < n; i++ {
			scanner.Scan()
			buf1 := strings.Split(scanner.Text(), " ")
			num[i], _ = strconv.Atoi(buf1[0])
			x[i], _ = strconv.Atoi(buf1[1])
			y[i], _ = strconv.Atoi(buf1[2])
			inv[num[i]] = i
		}
		for i := 0; i < n; i++ {
			for j := 0; j < n; j++ {
				dd[i][j]=(x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])
			}
		}
		scanner.Scan()
		m, _ := strconv.Atoi(scanner.Text())
		for i := 0; i < m; i++ {
			scanner.Scan()
			buf2 := strings.Split(scanner.Text(), " ")
			c, _ := strconv.Atoi(buf2[0])
			d, _ := strconv.Atoi(buf2[1])
			c = inv[c]
			d = inv[d]
			for j := 0; j < n; j++ {
				vv[j] = 0
				nowt[j]=999999999
				rev[j]=-1
			}
			nowt[c]=0
			for j := 0; j < n; j++ {
				M := 99999999
				at := 0
				for k := 0; k < n; k++ {
					if vv[k] == 0 && float64(M) > nowt[k] {
						M=int(nowt[k])
						at = k
					}
				}
				if M > 90000000 {
					break
				}
				vv[at]=1
				for k := 0; k < n; k++ {
					if vv[k] == 0 && dd[at][k]<=2500&&nowt[k]>nowt[at]+math.Sqrt(float64(dd[at][k])) {
						nowt[k]=nowt[at]+math.Sqrt(float64(dd[at][k]))
						rev[k] = at
					}
				}
			}
			if vv[d] == 0 {
				fmt.Println("NA")
			} else {
				stack := make([]int, 0)
				V := d
				for V != c {
					stack = append(stack, V)
					V = rev[V]
				}
				fmt.Print(num[c])
				for len(stack) > 0 {
					fmt.Printf(" %d", num[stack[len(stack)-1]])
					stack = stack[:len(stack)-1]
				}
				fmt.Println()
			}
		}
	}
}

C++: // clang-format off
#include <bits/stdc++.h>
using namespace std;
#define int long long
#define main signed main()
#define loop(i, a, n) for (int i = (a); i < (n); i++)
#define rep(i, n) loop(i, 0, n)
#define all(v) (v).begin(), (v).end()
#define rall(v) (v).rbegin(), (v).rend()
#define prec(n) fixed << setprecision(n)
constexpr int INF = sizeof(int) == sizeof(long long) ? 1000000000000000000LL : 1000000000;
constexpr int MOD = 1000000007;
constexpr double PI = 3.14159265358979;
template<typename A, typename B> bool cmin(A &a, const B &b) { return a > b ? (a = b, true) : false; }
template<typename A, typename B> bool cmax(A &a, const B &b) { return a < b ? (a = b, true) : false; }
bool odd(const int &n) { return n & 1; }
bool even(const int &n) { return ~n & 1; }
template<typename T = int> T in() { T x; cin >> x; return x; }
template<typename T = int> T in(T &&x) { T z(forward<T>(x)); cin >> z; return z; }
template<typename T> istream &operator>>(istream &is, vector<T> &v) { for (T &x : v) is >> x; return is; }
template<typename A, typename B> istream &operator>>(istream &is, pair<A, B> &p) { return is >> p.first >> p.second; }
template<typename T> ostream &operator<<(ostream &os, const vector<vector<T>> &v) { int n = v.size(); rep(i, n) os << v[i] << (i == n - 1 ? "" : "\n"); return os; }
template<typename T> ostream &operator<<(ostream &os, const vector<T> &v) { int n = v.size(); rep(i, n) os << v[i] << (i == n - 1 ? "" : " "); return os; }
template<typename A, typename B> ostream &operator<<(ostream &os, const pair<A, B> &p) { return os << p.first << ' ' << p.second; }
template<typename Head, typename Value> auto vectors(const Head &head, const Value &v) { return vector<Value>(head, v); }
template<typename Head, typename... Tail> auto vectors(Head x, Tail... tail) { auto inner = vectors(tail...); return vector<decltype(inner)>(x, inner); }
// clang-format on

struct Edge {
  int src, dst, id;
  Edge(const int &src, const int &dst, const int &id) : src(src), dst(dst), id(id) {}
  Edge(const int &src, const int &dst) : src(src), dst(dst), id(-1) {}
  Edge() : src(), dst(), id(-1) {}
  friend ostream &operator<<(ostream &os, const Edge &e) {
    return os << e.src << "->" << e.dst << " (id=" << e.id << ')';
    return os;
  }
};

template<typename Weight> struct WeightedEdge : Edge {
  Weight weight;

public:
  WeightedEdge(const int &src, const int &dst, const Weight &weight, const int &id) : Edge(src, dst, id), weight(weight) {}
  WeightedEdge(const int &src, const int &dst, const Weight &weight) : Edge(src, dst), weight(weight) {}
  WeightedEdge() : Edge(), weight() {}
  friend ostream &operator<<(ostream &os, const WeightedEdge<Weight> &e) {
    return os << e.src << "->" << e.dst << " (id=" << e.id << ", weight=" << e.weight << ')';
    return os;
  }
};

template<typename Edge> class Graph {
  int n;
  bool directed;
  vector<Edge> edges;

public:
  Graph(const int &n, const bool &directed = true) : n(n), directed(directed) {}
  template<typename... Args> void addEdge(Args... args) { edges.emplace_back(args..., edges.size()); }
  void addEdge(const Edge &edge) { edges.emplace_back(edge); }
  int sizeV() const { return n; }
  int sizeE() const { return edges.size(); }
  bool isDirected() const { return directed; }
  const Edge &operator[](const int &i) const { return edges[i]; }
  auto begin() { return edges.begin(); }
  auto begin() const { return edges.begin(); }
  auto end() { return edges.end(); }
  auto end() const { return edges.end(); }
  friend ostream &operator<<(ostream &os, const Graph<Edge> &g) {
    os << "V=" << g.sizeV() << ", E=" << g.sizeE() << ", directed=" << (g.isDirected() ? "true" : "false") << endl;
    for (auto &e : g.edges) os << e << endl;
    return os;
  }
};

template<typename Edge> class AdjList {
  bool directed;
  vector<vector<Edge>> al;

public:
  AdjList(const Graph<Edge> &g) : directed(g.isDirected()), al(g.sizeV()) {
    int m = g.sizeE();
    if (directed) {
      rep(i, m) al[g[i].src].emplace_back(g[i]);
    } else {
      rep(i, m) {
        al[g[i].src].emplace_back(g[i]);
        al[g[i].src].back().id = i << 1;
        al[g[i].dst].emplace_back(g[i]);
        swap(al[g[i].dst].back().src, al[g[i].dst].back().dst);
        al[g[i].dst].back().id = i << 1 | 1;
      }
    }
  }

  const auto &operator[](const int &i) const { return al[i]; }
  auto begin() { return al.begin(); }
  auto begin() const { return al.begin(); }
  auto end() { return al.end(); }
  auto end() const { return al.end(); }
};

template<typename Weight> class Dijkstra {
  int s;
  AdjList<WeightedEdge<Weight>> al;
  vector<Weight> dist;
  vector<Edge> prev;

public:
  Dijkstra(const Graph<WeightedEdge<Weight>> &g,
           const int &s,
           const Weight &inf = numeric_limits<Weight>::max() / 8) //
      : al(g), s(s), dist(g.sizeV(), inf), prev(g.sizeV()) {
    using state = pair<Weight, int>;
    priority_queue<state, vector<state>, greater<state>> q;
    dist[s] = 0;
    q.emplace(0, s);
    while (q.size()) {
      Weight d;
      int v;
      tie(d, v) = q.top();
      q.pop();
      if (dist[v] < d) continue;
      for (auto &e : al[v]) {
        if (cmin(dist[e.dst], dist[v] + e.weight)) {
          prev[e.dst] = e;
          q.emplace(dist[e.dst], e.dst);
        }
      }
    }
  }

  Weight shortestDist(const int &v) { return dist[v]; }

  vector<Edge> shortestPathEdges(int v) {
    vector<Edge> p;
    for (; v != s; v = prev[v].src) p.emplace_back(prev[v]);
    reverse(all(p));
    return p;
  }

  vector<int> shortestPathVertices(int v) {
    vector<Edge> es = shortestPathEdges(v);
    vector<int> p;
    for (auto &e : es) p.emplace_back(e.src);
    p.emplace_back(v);
    return p;
  }
};

main {
  while (true) {
    int n = in();
    if (n == 0) break;
    Graph<WeightedEdge<double>> g(n, false);
    vector<double> x(n), y(n);
    rep(i, n) {
      int b, x1, y1;
      cin >> b >> x1 >> y1;
      --b;
      x[b] = x1, y[b] = y1;
    }
    rep(i, n) loop(j, i + 1, n) {
      double d = hypot(x[i] - x[j], y[i] - y[j]);
      if (d <= 50.0) g.addEdge(i, j, d);
    }
    int m;
    cin >> m;
    while (m--) {
      int s, t;
      cin >> s >> t;
      --s, --t;
      Dijkstra<double> dij(g, s, INF);
      if (dij.shortestDist(t) == INF) {
        cout << "NA" << endl;
        continue;
      }
      auto p = dij.shortestPathVertices(t);
      for (auto &v : p) v++;
      cout << p << endl;
    }
  }
}