#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <cassert>

#if 0
#define dbg(...) fprintf(stderr, __VA_ARGS__),fflush(stderr)
#else
#define dbg(...)
#endif

using namespace std;

typedef std::pair <int, int> pii;

vector <pii> edges;
map <pii, int> edgeNum;

void makeSwap(pii nums) {
    swap(edges[nums.first], edges[nums.second]);
    edgeNum[edges[nums.first]] = nums.first;
    edgeNum[edges[nums.second]] = nums.second;
}

inline bool tryGetAnother(int edgeNum, int vertex, int & result) {
    const pii & edge = edges[edgeNum];
    if (edge.first == vertex) {
        result = edge.second;
        return true;
    }
    result = -1;
    return false;
}

inline int getAnother(int edgeNum, int vertex) {
    int result;
    if (tryGetAnother(edgeNum, vertex, result)) {
        return result;
    }
    throw 42;
}

class Path {
    vector <int> vertices;
    vector <int> edges;
    set <int> used_vertices;
public:
    Path(int start) {
        vertices.push_back(start);
        used_vertices.insert(start);
        dbg("start from %d\n", start);
    }

    bool wasUsed(int vert) const {
        return used_vertices.count(vert) != 0;
    }

    void addEdge(int edgeNum) {
        int next = getAnother(edgeNum, vertices.back());
        dbg("go to %d use edge %d\n", next, edgeNum);
        assert(used_vertices.count(next) == 0);
        edges.push_back(edgeNum);
        vertices.push_back(next);
        used_vertices.insert(next);
    }

    int length() const {
        return (int)edges.size();
    }

    bool empty() const {
        return length() == 0;
    }

    int lastVertex(int index) const {
        return vertices[vertices.size() - 1 - index];
    }

    int lastEdge(int index) const {
        return edges[edges.size() - 1 - index];
    }
};

Path scanPath(int from, vector <int> edgePath) {
    Path path(from);
    for (int i = 0; i < int(edgePath.size()); ++i) {
        int nextVertex;
        if (tryGetAnother(edgePath[i], path.lastVertex(0), nextVertex) && !path.wasUsed(nextVertex)) {
            path.addEdge(edgePath[i]);
        } else {
            break;
        }
    }
    return path;
}

class CandidatesForSwap {
    vector <pii> candidates;
public:
    void addSwap(int e1, int e2) {
        dbg("addSwap(%d %d)\n", e1, e2);
        if (e1 == e2) {
            return;
        }
        if (e1 > e2) {
            swap(e1, e2);
        }
        pii newSwap = pii(e1, e2);
        int i = 0;
        while (i < int(candidates.size()) && candidates[i] != newSwap) {
            ++i;
        }
        if (i == int(candidates.size())) {
            candidates.push_back(newSwap);
        }
    }

    vector <pii>::const_iterator begin() const {
        return candidates.begin();
    }

    vector <pii>::const_iterator end() const {
        return candidates.end();
    }
};

class SwapsSet {
    vector <pii> swaps;
    bool isUniversal;
public:
    SwapsSet() {
        isUniversal = true;
    }

    void intersectWith(vector <pii> swaps2) {
        sort(swaps2.begin(), swaps2.end());
        if (isUniversal) {
            isUniversal = false;
            swaps = swaps2;
        } else {
            vector <pii> swaps3;
            set_intersection(swaps.begin(), swaps.end(), swaps2.begin(), swaps2.end(), back_inserter(swaps3));
            swaps = swaps3;
        }
    }

    pii findAnyAllowed(const vector <bool> & canBeSwapped) const {
        if (isUniversal) {
            int i1 = 0;
            while (i1 < (int)canBeSwapped.size() && !canBeSwapped[i1]) {
                ++i1;
            }
            int i2 = i1 + 1;
            while (i2 < (int)canBeSwapped.size() && !canBeSwapped[i2]) {
                ++i2;
            }
            if (i2 < (int)canBeSwapped.size()) {
                return pii(i1, i2);
            }
            return pii(-1, -1);
        }
        for (const pii & sw : swaps) {
            if (canBeSwapped[sw.first] && canBeSwapped[sw.second]) {
                return sw;
            }
        }
        return pii(-1, -1);
    }
};

bool tryFindEdge(int u, int v, int &edgeNum) {
    map <pii, int>::iterator it = ::edgeNum.find(pii(u, v));
    if (it != ::edgeNum.end()) {
        edgeNum = it->second;
        return true;
    }
    edgeNum = -1;
    return false;
}

void tryFixDirection(int fromV, int toV, int oldE, CandidatesForSwap & candidates) {
    dbg("tryFixDirection(fromV = %d, toV = %d, oldE = %d)\n", fromV, toV, oldE);
    int edgeNum;
    if (tryFindEdge(fromV, toV, edgeNum)) {
        candidates.addSwap(oldE, edgeNum);
    }
}

void trySkipEdge(int to, const vector <int> & allPath, const Path & beginPath, int pos, CandidatesForSwap & candidatesForSwap) {
    int curVertex = beginPath.lastVertex(beginPath.length() - pos);
    int curEdge = allPath[pos];
    dbg("trySkipEdge(v = %d, e = %d)\n", curVertex, curEdge);
    if (pos + 1 == int(allPath.size())) {
        tryFixDirection(curVertex, to, curEdge, candidatesForSwap);
    } else {
        int nextEdge = allPath[pos + 1];
        candidatesForSwap.addSwap(curEdge, nextEdge);
        tryFixDirection(curVertex, edges[nextEdge].first, curEdge, candidatesForSwap);
        tryFixDirection(curVertex, edges[nextEdge].second, curEdge, candidatesForSwap);
    }
}

bool existsPath(int from, int to, const vector <int> & path) {
    Path scannedPath = scanPath(from, path);
    return scannedPath.length() == int(path.size()) && scannedPath.lastVertex(0) == to;
}

int main() {
    freopen("zoo.in", "r", stdin);
    freopen("zoo.out", "w", stdout);

    int n, m;
    scanf("%d%d", &n, &m);
    edges.resize(m);
    for (int i = 0; i < m; ++i) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        --u, --v, --w;
        edges[w] = pii(u, v);
        edgeNum[pii(u, v)] = w;
    }

    vector <bool> canBeSwapped(m, true);

    SwapsSet resultSet;

    int k;
    scanf("%d", &k);
    for (int i = 0; i < k; ++i) {
        dbg("i = %d\n", i);
        int t;
        scanf("%d", &t);
        int from, to;
        scanf("%d%d", &from, &to);
        --from, --to;

        vector <int> path(t);
        for (int j = 0; j < t; ++j) {
            scanf("%d", &path[j]);
            --path[j];
        }

        Path beginPath = scanPath(from, path);
        if (beginPath.length() == (int)path.size() && beginPath.lastVertex(0) == to) {
            for (int j = 0; j < int(path.size()); ++j) {
                canBeSwapped[path[j]] = false;
            }
            continue;
        }

        CandidatesForSwap candidatesForSwap;
        if (beginPath.length() >= 2) {
            tryFixDirection(beginPath.lastVertex(2), beginPath.lastVertex(0), beginPath.lastEdge(1), candidatesForSwap);
        }
        if (beginPath.length() >= 1) {
            trySkipEdge(to, path, beginPath, beginPath.length() - 1, candidatesForSwap);
        }
        if (beginPath.length() < int(path.size())) {
            trySkipEdge(to, path, beginPath, beginPath.length(), candidatesForSwap);
        }

        vector <pii> swaps;
        for (const pii & candSwap : candidatesForSwap) {
            makeSwap(candSwap);
            dbg("check swap %d <-> %d\n", candSwap.first, candSwap.second);
            if (existsPath(from, to, path)) {
                swaps.push_back(candSwap);
                dbg("found good swap %d <-> %d\n", candSwap.first, candSwap.second);
            }
            makeSwap(candSwap);
        }
        resultSet.intersectWith(swaps);
    }

    pii resSwap = resultSet.findAnyAllowed(canBeSwapped);
    printf("%d %d\n", resSwap.first + 1, resSwap.second + 1);

    return 0;
}
