/* An O(N^3 log^2 N) time, O(N^2) space solution.
   Plenty opportunity for ad-hoc optimization left. */

import java.util.*;

public class maks
{
    public static void main(String[] args)
    {
        Scanner sc = new Scanner(System.in);
        int cases = sc.nextInt();
        while (cases-- > 0)
        {
            // Read input
            int N = sc.nextInt();           // number of nodes
            int M = sc.nextInt();           // number of edges
            int[]   A = new int[N];         // altitudes of nodes
            int[][] D = new int[N][N];      // distance between adjacent nodes
            for (int n = 0; n < N; ++n)
                A[n] = sc.nextInt();
            for (int m = 0; m < M; ++m)
            {
                int i = sc.nextInt() - 1, j = sc.nextInt() - 1, d = sc.nextInt();
                if (D[i][j] == 0 || d < D[i][j])
                    D[i][j] = D[j][i] = d;
            }

            // Create a sorted list of distinct altitudes
            int[] orderedAlts;
            {
                TreeSet<Integer> set = new TreeSet<Integer>();
                for (int h : A)
                    set.add(h);
                orderedAlts = new int[set.size()];
                Iterator<Integer> it = set.iterator();
                int n = 0;
                while (it.hasNext())
                    orderedAlts[n++] = it.next();
            }

            int bestDiff = Integer.MAX_VALUE, bestLength = Integer.MAX_VALUE;

            // Try all minimum altitudes
            for (int minAlt : orderedAlts)
            {
                // Binary search for first maximum altitude that yields a path
                int lo = 0, hi = orderedAlts.length;
                while (lo < hi)
                {
                    int mid = (lo + hi)/2;
                    int maxAlt = orderedAlts[mid];

                    // Check if a path exists using Dijkstra's algorithm
                    PriorityQueue<Integer> pq = new PriorityQueue<Integer>();
                    boolean[] visited = new boolean[N];
                    if (minAlt <= A[0] && A[0] <= maxAlt)
                        pq.add(0);
                    int length = -1;
                    while (!pq.isEmpty())
                    {
                        int node = pq.peek()%N, dist = pq.peek()/N;
                        pq.poll();

                        if (visited[node])
                            continue;
                        visited[node] = true;

                        if (node == N - 1)
                            length = dist;      // shortest path found!

                        for (int next = 0; next < N; ++next)
                            if (!visited[next] && D[node][next] != 0 &&
                                minAlt <= A[next] && A[next] <= maxAlt)
                            {
                                pq.add(next + N*(dist + D[node][next]));
                            }
                    }

                    if (length == -1)
                    {
                        lo = mid + 1;   // No path found; raise lower bound
                    }
                    else
                    {
                        hi = mid;       // Path found! Lower upper bound

                        // Update best solution
                        int diff = maxAlt - minAlt;
                        if (diff < bestDiff || (diff == bestDiff && length < bestLength))
                        {
                            bestDiff   = diff;
                            bestLength = length;
                        }
                    }
                }
            }
            System.out.println(bestDiff + " " + bestLength);
        }
    }
}
