// Arup Guha
// 3/14/2020
// Solution to 2020 UCF HS Contest Problem: Gamers on the Bus

import java.util.*;

public class bus {
	
	// Look at spec to fix this.
	final public static double NOPATH = 3000.0*2000000.0;
	final public static double EPS = 1e-9;
	
	// Store points.
	public static int n;
	public static int[] x;
	public static int[] y;
	
	// Graph...and storing unique vertex answers.
	public static ArrayList[] g;	
	public static HashMap<Integer,Integer> oneAnsVertex;
	
	public static void main(String[] args) {
	
		Scanner stdin = new Scanner(System.in);
		int nC = stdin.nextInt();
		
		// Process all cases.
		for (int loop=0; loop<nC; loop++) {
			
			// Get # vertices, edges
			n = stdin.nextInt();
			int numE = stdin.nextInt();
			
			// Store locations.
			x = new int[n];
			y = new int[n];
			for (int i=0; i<n; i++) {
				x[i] = stdin.nextInt();
				y[i] = stdin.nextInt();
			}
			
			// Empty graph.
			g = new ArrayList[n];
			for (int i=0; i<n; i++)
				g[i] = new ArrayList<edge>();
			
			// Now, add edges.
			for (int i=0; i<numE; i++) {
				int u = stdin.nextInt();
				int v = stdin.nextInt();
				double w = Math.sqrt((x[u]-x[v])*(x[u]-x[v])+(y[u]-y[v])*(y[u]-y[v]));
				g[u].add(new edge(u, v, w));
				g[v].add(new edge(v, u, w));
			}
			
			// I know we have to run these two...
			double[] distFromStart = dijkstras(0);
			double[] distFromEnd = dijkstras(n-1);
			
			// Pre-comp stuff.
			TreeSet<Double> uniqueD = new TreeSet<Double>();
			boolean[] onPath = new boolean[n];
			for (int i=0; i<n; i++) {
				if (Math.abs(distFromStart[i]+distFromEnd[i]-distFromStart[n-1]) < EPS) {
					onPath[i] = true;
					Double mappedVal = mapme(distFromStart[i]);
					uniqueD.add(mappedVal);
				}
			}
			
			// This tree map stores each unique shortest distance from the source to an alternate index.
			TreeMap<Double,Integer> altIdx = new TreeMap<Double,Integer>();
			double[] levels = new double[uniqueD.size()];
			int myidx = 0;
			while (uniqueD.size() > 0) {
				double val = uniqueD.pollFirst();
				altIdx.put(val, myidx);
				levels[myidx] = val;
				myidx++;
			}
			
			int[] covered = new int[altIdx.size()];
			
			// For each edge, identify if it's on a shortest path.
			ArrayList<edge> shortPathEdges = new ArrayList<edge>();
			for (int i=0; i<n; i++) {
				for (edge e: (ArrayList<edge>)g[i]) {
					if (onPath[e.u] && onPath[e.v] && distFromEnd[e.u] > distFromEnd[e.v]) {
						shortPathEdges.add(e);
						int mys = altIdx.get(mapme(distFromStart[e.u]));
						int mye = altIdx.get(mapme(distFromStart[e.v]));
						for (int k=mys; k<mye; k++) covered[k]++;
					}
				}
			}
			
			// Fills for different
			edge[] whichEdge = new edge[altIdx.size()];
			Arrays.fill(whichEdge, null);
			for (edge e: shortPathEdges) {
				int mys = altIdx.get(mapme(distFromStart[e.u]));
				int mye = altIdx.get(mapme(distFromStart[e.v]));
				if (covered[mys] == 1) 
					for (int k=mys; k<mye; k++) whichEdge[k] = e;
			}
			
			// Store unique answers here.
			oneAnsVertex = new HashMap<Integer,Integer>();
			HashSet<Integer> usedD = new HashSet<Integer>();
			for  (int i=0; i<n; i++) {
				
				// Irrelevent vertices.
				if (!onPath[i]) continue;
				
				// Since queries are only integers, I don't care about these.
				if (notInt(distFromStart[i])) continue;
				
				int d = (int)(distFromStart[i]+EPS);
				
				// Not a unique distance.
				if (usedD.contains(d)) {
					if (oneAnsVertex.containsKey(d)) oneAnsVertex.remove(d);
					continue;
				}
				
				// Add to used, store unique vertex at this distance.
				usedD.add(d);
				oneAnsVertex.put(d, i);
			}
			
			// Process queries.
			int numQ = stdin.nextInt();
			for (int i=0; i<numQ; i++) {
				int sofar = stdin.nextInt();
				
				
				// At a vertex and it's the only one.
				if (oneAnsVertex.containsKey(sofar)) {
					
					// A unique distance on a shortest path.
					int v = oneAnsVertex.get(sofar);
					
					// Get the alternate index in our other map.
					int newIdx = altIdx.get(mapme(distFromStart[v]));
					
					// This means there are two ways from this vertex.
					if (whichEdge[newIdx] == null)
						System.out.println("Best of Luck");
					
					// Woo hoo!
					else
						System.out.printf("%.2f %.2f\n", 1.0*x[v], 1.0*y[v]);
				}
				
				// All other cases are here.
				else {
				
					// Find which "segment" we are on.
					int sE = binarySearch(levels, sofar);
					
					// This means there is more than one way.
					if (whichEdge[sE] == null)
						System.out.println("Best of Luck");
					
					// We can do it - just calculate how far on this edge we must travel.
					else {
						edge e = whichEdge[sE];
						double toGo = sofar - distFromStart[e.u];
						int dx = x[e.v] - x[e.u];
						int dy = y[e.v] - y[e.u];
						double ratio = toGo/Math.sqrt(dx*dx+dy*dy);
						double newx = x[e.u] + ratio*dx;
						double newy = y[e.u] + ratio*dy;
						System.out.printf("%.2f %.2f\n", newx, newy);
					}
				}
			}
		}
	}
	
	// Returns the max value of i such that levels[i] <= sofar.
	public static int binarySearch(double[] levels, int sofar) {
		int low = 0, high = levels.length-1;
		while (low < high) {
			int mid = (low+high+1)/2;
			if (sofar > levels[mid])
				low = mid;
			else
				high = mid-1;
		}
		return low;
	}
	
	// Maps d to a Double object written to exactly 6 decimal places. This is to make my hashmap work.
	public static Double mapme(double d) {
		long tmp = (long)(d*1000000);
		long intpart = tmp/1000000;
		long decimal = tmp%1000000;
		Double res = new Double(intpart + decimal/1000000.0);
		return res;
	}
	
	// Returns true iff d isn't an integer.
	public static boolean notInt(double d) {
		int tmp = (int)(d+EPS);
		return Math.abs(d-tmp) > EPS;
	}
	
	// Runs Dijkstra's from vertex u returning all distances from u to the rest of the vertices.
	public static double[] dijkstras(int u) {
		
		double[] dist = new double[n];
		Arrays.fill(dist, NOPATH);
		PriorityQueue<edge> pq = new PriorityQueue<edge>();
		pq.offer(new edge(-1,u,0.0));
		int done = 0;
		
		// Keep on going until queue empties or we have all our shortest distances.
		while (pq.size() > 0 && done < n) {
			
			edge cur = pq.poll();
			
			// We've done this one before.
			if (dist[cur.v] < NOPATH-1) continue;
			
			// Store distance, mark done.
			dist[cur.v] = cur.w;
			done++;
			
			// Try getting better estimates.
			for (edge next: (ArrayList<edge>)g[cur.v]) {
				
				// No need to put this in the queue.
				if (dist[next.v] < NOPATH-1) continue;
				
				// This is our new distance to next.w.
				pq.offer(new edge(next.u, next.v, cur.w+next.w));
			}
		}
		
		// Here are all the shortest distances from u
		return dist;
	}
}

class edge implements Comparable<edge> {

	public int u;
	public int v;
	public double w;
	
	public edge(int myu, int myv, double myw) {
		u = myu;
		v = myv;
		w = myw;
	}
	
	public edge(edge copy) {
		u = copy.u;
		v = copy.v;
		w = copy.w;
	}
	
	public int compareTo(edge other) {
		if (w - other.w < -1e-9) return -1;
		if (other.w - w < -1e-9) return 1;
		return 0;
	}
}