/*
 * Sample solution to Easter Holidays
 * Author: Mikael Goldmann
 */

import java.io.*;
import java.util.*;


class holidays_mg 
{
    static BufferedReader stdin;
    static final int infty = 1<<30;
    

    public static void main(String[] s) throws Exception
    {
	Reader r = new InputStreamReader(System.in);
	stdin = new BufferedReader(r);
	
	(new holidays_mg()).run();
	
    }
    

    void run() throws Exception
    {
	int ncases=Integer.parseInt(stdin.readLine());
	for (int i = 0; i < ncases; ++i)
	    solve(i+1);
    }
    

    void solve(int casenum)  throws Exception
    {
	int n,m,k;
	StringTokenizer st;
	
	st = new StringTokenizer(stdin.readLine());
	n = Integer.parseInt(st.nextToken());
	m = Integer.parseInt(st.nextToken());
	k = Integer.parseInt(st.nextToken());

	/* read input into int arrays */
	int[] slopefrom = new int[m];
	int[] slopeto = new int[m];
	int[] slopecost = new int[m];
	int[] liftfrom = new int[k];
	int[] liftto = new int[k];
	int[] liftcost = new int[k];
	int[] nslopes = new int[n+1];
	int[] nlifts = new int[n+1];

	for (int i = 0; i < m; ++i) {
	    st = new StringTokenizer(stdin.readLine());
	    slopefrom[i] =  Integer.parseInt(st.nextToken());
	    slopeto[i] =  Integer.parseInt(st.nextToken());
	    slopecost[i] =  Integer.parseInt(st.nextToken());
	    ++nslopes[slopeto[i]];
	}
	for (int i = 0; i < k; ++i) {
	    st = new StringTokenizer(stdin.readLine());
	    liftfrom[i] =  Integer.parseInt(st.nextToken());
	    liftto[i] =  Integer.parseInt(st.nextToken());
	    liftcost[i] =  Integer.parseInt(st.nextToken());
	    ++nlifts[liftfrom[i]];
	}

	/* slopes are modelled as edgees FROM the lower point 
	   (i.e., the "to") 
	   lifts are modelled as edgees FROM the lower point 
	   (i.e., the "from") 
	   For each place i, lift[i] is an array of places it has lifts to
	   and lcost[i] is an array of the correspoding costs.
	   Similarly for slope[i] and scost[i].
	   Note that slopes go up and are given negative costs!
	*/
	int[][] lift = new int[n+1][];
	int[][] slope = new int[n+1][];
	int[][] lcost = new int[n+1][];
	int[][] scost = new int[n+1][];
	int[] lcnt = new int[n+1];
	int[] scnt = new int[n+1];
	
	for (int i=1; i<=n; ++i) {
	    lift[i] = new int[nlifts[i]];
	    lcost[i] = new int[nlifts[i]];
	    slope[i] = new int[nslopes[i]];
	    scost[i] = new int[nslopes[i]];
	}
	
	for (int i = 0; i < m; ++i) {
	    int a = slopeto[i];
	    int b = slopefrom[i];
	    int c = -slopecost[i];
	    
	    slope[a][scnt[a]] = b;
	    scost[a][scnt[a]] = c;
	    ++scnt[a];
	}
	
	for (int i = 0; i < k; ++i) {
	    int a = liftfrom[i];
	    int b = liftto[i];
	    int c = liftcost[i];
	    
	    lift[a][lcnt[a]] = b;
	    lcost[a][lcnt[a]] = c;
	    ++lcnt[a];
	}
	
	/* us[1..n] will hold places sorted topologically by slopes */
	/* ul[1..n] will hold places sorted topologically by lifts */

	/*
	int[] us = new int[n+1];
	int[] ul = new int[n+1];
	
	topsort(n, us, slope);
	topsort(n, ul, lift);
	*/
	int[] ds = new int[n+1];
	int[] dl = new int[n+1];
	int[] sp = new int[n+1]; // backpointer
	int[] lp = new int[n+1]; // backpointer

	double best = -1.0;
	int bestlen = 0;
	int[] besttrip = new int[2*n];
	int[] aux = new int[n];
	
	for (int i = 1; i <= n; ++i) {
	    Arrays.fill(ds, infty);
	    Arrays.fill(dl, infty);
	    DAGshortestPath(n, i, slope, scost, ds, sp);
	    /*
	    for (int ii = 1; ii <= n; ++ii)
		System.err.println(ii +": " + ds[ii] + ", " + sp[ii]);
	    */
	    DAGshortestPath(n, i, lift, lcost, dl, lp);
	    /*
	    for (int ii = 1; ii <= n; ++ii)
		System.err.println(ii +": " + dl[ii] + ", " + lp[ii]);
	    */
	    for (int j = 1; j <= n; ++j) {
		if (dl[j] < infty && ds[j] < infty
		    && dl[j] != 0) {
		    
		    double score = -ds[j];
		    score /= dl[j];
		    if (score > best) {
			best = score;
			/*
			System.err.println("i= " + i + "  j= " +j);
			System.err.println("ds= " + ds[j] + "  dl= " +dl[j]);
			*/
			// save the trip
			int len1=0;
			int tmp = j;
			besttrip[len1++] = j;			
			while (tmp != i) {
			    tmp = lp[tmp];
			    besttrip[len1++] = tmp;
			}
			int len2 = 0;
			tmp = j;
			while (tmp != i) {
			    aux[len2++] = tmp;
			    tmp = sp[tmp];
			}
			for (int jj=len2-1; jj >= 0; --jj)
			    besttrip[len1++] = aux[jj];		    
			bestlen = len1;
		    }
		    
		}
	    }
	}
	System.out.print(besttrip[0]);
	for (int i = 1; i < bestlen; ++i) 
	    System.out.print(" " + besttrip[i]);
	System.out.println();

	long bst = Math.round(1000*best);
	System.out.print(bst/1000 + ".");
	bst %= 1000;
	int tt = 100;
	
	for (int ii = 0; ii < 3; ++ii) {
	    System.out.print(bst/tt);
	    bst %= tt;
	    tt /= 10;
	}
	System.out.println();
    }
    
    void DAGshortestPath(int n, int start, int[][]edges,
			 int[][] costs,
			 int[] dist, int[] prev) 
    {
	boolean[] visited = new boolean[n+1];
	dist[start] = 0;
	visited[start] = true;
	for (int i = 1; i <= n; ++i)
	    if (!visited[i]) 
		dfs(i, edges, costs, dist, prev, visited);
	
    }
    
    void dfs(int u, int[][] e, int[][] c, int[] d, int[] p, boolean[] v) 
    {
	int m = e[u].length;
	v[u] = true;
	for (int i = 0; i < m; ++i) {
	    int w = e[u][i];
	    if (!v[w]) dfs(w, e, c, d, p, v);
	    if (d[w] != infty && d[u] > d[w] + c[u][i]) {
		p[u] = w;
		d[u] = d[w] + c[u][i];
	    }
	}
    }
	    
}

