import java.util.*;

public  class DijkstraExample {
    
    public static Graph g;
    
    public static void main(String[] Args) {
        Scanner sc = new Scanner(System.in);
        Graph g = new Graph();
        int n = sc.nextInt();
        int e = sc.nextInt();
        
        for (int i = 0; i < n; i++) {
            if (g.getIndex(sc.next()) != i) {
                System.err.println("Duplicate Node Name");
            }
        }
        if (g.name_list.size() != n) {
            System.err.println("Not enough unique names!");
        }
        
        // Read in the graph
        for (int i = 0; i < e; i++) {
                
            // Get the start and end index
            String stName = sc.next();
            String enName = sc.next();
            double dist = sc.nextDouble();
            
            int st = g.getIndex(stName);
            int en = g.getIndex(enName);
            
            if (st >= n || en >= n) {
                System.err.println("Names not in the initial set");
                System.err.println(stName);
                System.err.println(enName);
            }
            
            // Add the edge
            g.add(st, en, dist);
            
            // Assuming the graph is bidirectional
            g.add(en, st, dist);
        }
        
        // Print the number of vertices
        System.out.println(g.n);
        
        // Get the beginning end ending city
        int startCity = g.getIndex(sc.next());
        int endCity = g.getIndex(sc.next());
        
        if (startCity >= n || endCity >= n) {
            System.err.println("Invalid query cities");
            return;
        }
        
        // Do a Dijkstras
        Dijkstras(g, startCity, endCity);
    }
    
    public static double oo = 987654321.0;
    public static int IMPOSSIBLE = -1;
    
    public static void Dijkstras(Graph g, int st, int en){
        
        // Make the visited array
        boolean[] visited = new boolean[g.n];
        double[] distances = new double[g.n];
        int[] prevCity = new int[g.n];
        
        // Fill the distances with large values
        Arrays.fill(distances, oo);
        distances[st] = 0.0;
        
        // Fill the previous cities with impossible values
        Arrays.fill(prevCity, IMPOSSIBLE);
        
        // Make a priority queue for the cities
        PriorityQueue<Pair> pq = new PriorityQueue<Pair>();
        
        // Add the pair to the priority queue
        pq.add(new Pair(st, 0.0));
        
        // Loop while the priority queue is not empty
        while (!pq.isEmpty() && !visited[en]) {
            
            // Get the next pair
            Pair curPair = pq.poll();
            int curCity = curPair.city;
            double curDist = curPair.dist;
            
            // Check if the city was visited
            if (visited[curCity]) {
                continue;
            }
            
            // Loop through adjacent cities
            for (Edge e : g.adj_list.get(curCity)) {
                
                // Get the destination of the edge
                int nextCity = e.en;
                
                // Compute the distance to the city by using this edge
                double newDist = curDist + e.w;
                
                // Check if the city is not visited
                if (!visited[nextCity] && 
                // Check that the distance is improved
                    newDist < distances[nextCity]) {
                    
                    // Update the distance with the better value
                    distances[nextCity] = newDist;
                    
                    // Update the previous city in the path
                    prevCity[nextCity] = curCity;
                    
                    // Put the pair of city and distance into the priority Queue
                    pq.add(new Pair(nextCity, newDist));
                }
            }
            
            // Set the city as visited
            visited[curCity] = true;
        }
        
        // Extract the path if possible
        if (prevCity[en] != IMPOSSIBLE) {
            // Compute the reverse order of the cities by pushing on to a stack and popping off later
            ArrayDeque<Integer> stk = new ArrayDeque<Integer>();
            int curCity = en;
            while (curCity != IMPOSSIBLE) {
                stk.addLast(curCity);
                curCity = prevCity[curCity];
            }
            
            // Create an in order list of cities to visit
            ArrayList<Integer> inOrderCities = new ArrayList<Integer>();
            
            // Pop off the stack into our list of cities
            while (!stk.isEmpty()) {
                inOrderCities.add(stk.pollLast());
            }
            
            // Print the cities
            for (int i = 1; i < inOrderCities.size(); i++) {
                
                // Get the indices
                int bIndex = inOrderCities.get(i - 1);
                int eIndex = inOrderCities.get(i);
                
                // Get the names
                String bName = g.name_list.get(bIndex);
                String eName = g.name_list.get(eIndex);
                
                // Get the path length
                double pathLength = distances[eIndex] - distances[bIndex];
                
                // Print the information
                System.out.println("Go from " + bName + " to " + eName + " with a distance of " + pathLength);            
            }
            
            // Print the total distance
            System.out.println("Total distance is " + distances[en]);
            
        } else {
            System.out.println(g.name_list.get(en) + " cannot be reached by " + g.name_list.get(st));
        }
    }
    
    public static class Pair implements Comparable<Pair> {
        int city;
        double dist;
        
        Pair(int city, double dist) {
            this.city = city;
            this.dist = dist;
        }
        
        public int compareTo(Pair o) {
            return Double.compare(this.dist, o.dist);
        }
    }
    
    public static class Graph {
        
        ArrayList<ArrayList<Edge>> adj_list;
        ArrayList<ArrayList<Edge>> rev_adj;
        HashMap<String, Integer> name_to_index;
        ArrayList<String> name_list;
        int n;
        
        Graph(){
            n = 0;
            
            // Allocate some memory
            adj_list = new ArrayList<ArrayList<Edge>>();
            rev_adj = new ArrayList<ArrayList<Edge>>();
            name_to_index = new HashMap<String, Integer>();
            name_list = new ArrayList<String>();
        }
        
        int getIndex(String s) {
        
            // Check if the name is not in the list of names
            if (!name_to_index.containsKey(s)) {
                name_to_index.put(s, n);
                name_list.add(s);
                adj_list.add(new ArrayList<Edge>());
                rev_adj.add(new ArrayList<Edge>());
                n++;
            }
            
            // Return the index for the given name
            return name_to_index.get(s);
        }
        
        void add(int i, int j, double w) {
            // Make the edges
            Edge fwd = new Edge(i, j, w);
            Edge rev = new Edge(j, i, w);
            
            // Set the reverse Edge pointers
            fwd.rev = rev;
            rev.rev = fwd;
            
            // Put the edges in the appropriate lists
            rev_adj.get(j).add(rev);
            adj_list.get(i).add(fwd);
        }
    }
    
    public static class Edge {
        int st, en;
        double w;
        Edge rev;
        
        Edge(int ss, int ee, double ww) {
            st = ss;
            en = ee;
            w = ww;
            rev = null;
        }
    }
}