// Arup Guha
// 6/17/2026
// Solution to Kattis Problem: Big Truck
// https://open.kattis.com/problems/bigtruck

using namespace std;

#include <iostream>
#include <vector>
#include <queue>

#define INF 1000000000

struct edge {

    int to;
    int w;
    int goodies;

    // Adjust to their definition, weight is still most important.
    bool operator<(const edge& other) const {
        if (w != other.w)
            return w > other.w;

        // Here we flip the comparison because more goodies is better.
        return goodies < other.goodies;
    }
};

pair<int,int> dijkstra(vector<vector<edge>>& graph, int v, int dest);

int main() {

    // Read in the goodies.
    int n, numE, v1, v2, w;
    cin >> n;
    vector<int> goodies(n);
    for (int i=0; i<n; i++)
        cin >> goodies[i];

    // Store graph here.
    vector<vector<edge>> graph(n);

    cin >> numE;

    // Read in the edges - add both ways.
    for (int i=0; i<numE; i++) {
        cin >> v1 >> v2 >> w;
        v1--; v2--;
        graph[v1].push_back(edge{v2,w,goodies[v2]});
        graph[v2].push_back(edge{v1,w,goodies[v1]});
    }

    // Run Dijkstra from start vertex to destination vertex.
    pair<int,int> res = dijkstra(graph, 0, n-1);

    // This is the output they want.
    if (res.first == -1)
        cout << "impossible" << endl;

    // Note: We never added in the goodies at the start...
    else
        cout << res.first << " " << res.second+goodies[0] << endl;

    return 0;
}

// Returns the list of shortest distances in g from vertex v via Dijkstra's Algorithm.
pair<int,int> dijkstra(vector<vector<edge>>& graph, int v, int dest) {

    // Safe initial values.
    int n = graph.size();
    vector<edge> dist(n);
    for (int i=0; i<n; i++) {
        dist[i].to = i;
        dist[i].w = INF;
        dist[i].goodies = 0;
    }

    // We start here.
    dist[v].w = 0;

    // Add source vertex to priority queue.
    // PQ stores edges (to, weight, goodies)
    priority_queue<edge> pq;
    pq.push(dist[v]);

    // Run Dijkstra.
    while (pq.size() > 0) {

        // Get next.
        edge cur = pq.top(); pq.pop();

        // If we already found a better distance, don't waste time checking this vertex again
        if (cur < dist[cur.to]) continue;

        // We're there!
        if (cur.to == dest)
            return pair<int,int>{cur.w,cur.goodies};

        // Check all neighbors for new best paths.
        for (auto x = graph[cur.to].begin(); x!=graph[cur.to].end(); x++) {

            // This is the new estimate.
            edge tmp{(*x).to, dist[cur.to].w+(*x).w, dist[cur.to].goodies+(*x).goodies};

            /*** This is super annoying. It looks backwards, and that's because C++ priority queue is a
                 max queue, so I already defined < to be the opposite of what it is intuitively.
            ***/
            if (dist[(*x).to] < tmp) {

                // Update
                dist[(*x).to] = tmp;

                // Insert into priority queue
                pq.push(tmp);
            }
        }
    }

    // Never made it.
    return pair<int,int>{-1,-1};
}
