import java.util.*;

public  class TopoSort {
    
    public static Graph g;
    
    public static void main(String[] Args) {
        Scanner sc = new Scanner(System.in);
        Graph g = new Graph();
        
        // Read in the graph
        while (sc.hasNextLine()) {
            // Read in a line
            String line = sc.nextLine().trim();
            
            // Check if the line is an edge
            if (line.contains("-->")) {
                String[] tokes = line.split("-->");
                
                // Get the start and end index
                int st = g.getIndex(tokes[0].trim());
                int en = g.getIndex(tokes[1].trim());
                
                // Add the edge
                g.add(st, en, 1);
            }
        }
        
        // Print the number of vertices
        System.out.println(g.n);
        
        // Do what you want
        for (int i = 0; i < g.n; i++) {
            System.out.print(g.name_list.get(i) +" : ");
            for (Edge e : g.adj_list.get(i))
                System.out.print(g.name_list.get(e.en) +" ");
            System.out.println();
        }
        
        // BFS
        // BFS(g);
        
        // DFS
        // DFS(g);
        
        // BFS topo
        //BFSTopo(g);
        
        // DFS Topo
        DFSTopo(g);
    }
    
    public static void DFSTopo(Graph g) {
        int n = g.n;
        
        boolean[] visited = new boolean[n];
        int[] inDeg = new int[n];
        
        for (int i = 0; i < n; i++)
            inDeg[i] = g.rev_adj.get(i).size();
        
        for (int i = 0; i < n; i++) {
            if (!visited[i] && inDeg[i] == 0) {
                visited[i] = true;
                DFSTopo(i, g, visited, inDeg, 0);
            }
        }
    }
    
    public static void DFSTopo(int cur, Graph g, boolean[] visited, int[] inDeg, int dist) {
        System.out.println("Class " + g.name_list.get(cur) +" at distance " + dist);
        for (Edge e : g.adj_list.get(cur)) {
            inDeg[e.en]--;
            if (inDeg[e.en] == 0 && !visited[e.en]) {
                visited[e.en] = true;
                DFSTopo(e.en, g, visited, inDeg, dist + 1);
            }
        }
    }
    
    public static void BFSTopo(Graph g) {
        int n = g.n;
        
        boolean[] visited = new boolean[n];
        int cc = 0;
        
        Queue<Integer> q = new LinkedList<Integer>();
        int[] inDeg = new int[n];
        
        for (int i = 0; i < n; i++)
            inDeg[i] = g.rev_adj.get(i).size();
        
        for (int i = 0; i < n; i++) {
            if (!visited[i] && inDeg[i] == 0) {
                q.add(i);
                q.add(1);
            }
        }
        
        while (!q.isEmpty()) {
            int cur = q.poll();
            int semester = q.poll();
            System.out.println(g.name_list.get(cur) +" in Semester " + semester);
            
            // Look through out edges
            for (Edge e : g.adj_list.get(cur)) {
                inDeg[e.en]--;
                if (inDeg[e.en] == 0) {
                    // Add element to queue
                    q.add(e.en);
                    q.add(semester + 1);
                }
            }
        }
    }
    
    public static void BFS(Graph g) {
        int n = g.n;
        
        // Make a list of visited markers
        boolean[] visited = new boolean[n];
        int cc = 1;
        
        // Look through each node
        for (int i = 0; i < n; i++) {
            if (!visited[i]) {
                System.out.println("In Component " + (cc++));
                Queue<Integer> q = new LinkedList<Integer>();
                q.add(i);
                q.add(0);
                visited[i] = true;
                
                while (!q.isEmpty()) {
                    int cur = q.poll();
                    int dist = q.poll();
                    
                    System.out.println("Class " + g.name_list.get(cur) +" distance from original is " + dist);
                    
                    // Check the forward Edges
                    for (Edge e : g.adj_list.get(cur)) {
                        if (!visited[e.en]) {
                            visited[e.en] = true;
                            q.add(e.en);
                            q.add(dist + 1);
                        }
                    }
                    
                    // Check the reverse Edges
                    for (Edge e : g.rev_adj.get(cur)) {
                        if (!visited[e.en]) {
                            visited[e.en] = true;
                            q.add(e.en);
                            q.add(dist + 1);
                        }
                    }
                }
                
                System.out.println();
            }
        }
    }
    
    
    public static void DFS(Graph g) {
        int n = g.n;
        
        boolean[] visited = new boolean[n];
        int cc = 1;
        for (int i = 0; i < n; i++)
            if (!visited[i]) {
                System.out.println("Component " + cc++);
                visited[i] = true;
                DFS(i, g, visited, 0);
                System.out.println();
            }
    }
    
    public static void DFS(int cur, Graph g, boolean[] visited, int dist) {
        System.out.println("Class " + g.name_list.get(cur) + " distance " + dist);
        for (Edge e : g.adj_list.get(cur)) {
            if (!visited[e.en]) {
                visited[e.en] = true;
                DFS(e.en, g, visited, dist + 1);
            }
        }
        
        for (Edge e : g.rev_adj.get(cur)) {
            if (!visited[e.en]) {
                visited[e.en] = true;
                DFS(e.en, g, visited, dist + 1);
            }
        }
    }
    
    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, int 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, w;
        Edge rev;
        
        Edge(int ss, int ee, int ww) {
            st = ss;
            en = ee;
            w = ww;
            rev = null;
        }
    }
}