import java.io.*; import java.util.*; /** * This solution works by searching over all triples of vertices, * representing the locations of the 3 robots. Secondary colour * edges can only be traversed if the two appropriate robots are * at the same vertex with the incident secondary colour edge. * * @author Finn Lidbetter */ public class TripleSearch { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] s = br.readLine().split(" "); int n = Integer.parseInt(s[0]); int m = Integer.parseInt(s[1]); int r0 = Integer.parseInt(s[2]) - 1; int b0 = Integer.parseInt(s[3]) - 1; int y0 = Integer.parseInt(s[4]) - 1; Node[] nodes = new Node[n]; Edge[] edges = new Edge[m]; for (int i=0; i q = new LinkedList<>(); q.offer(new Triple(r0,b0,y0)); while (q.size()>0) { Triple curr = q.poll(); // Move robots along unspecified edges. for (Edge e: nodes[curr.r].adjX) { Triple next = new Triple(e.v, curr.b, curr.y); if (!nodeTripleVis[next.r][next.b][next.y]) { q.offer(next); nodeTripleVis[next.r][next.b][next.y] = true; } } for (Edge e: nodes[curr.b].adjX) { Triple next = new Triple(curr.r, e.v, curr.y); if (!nodeTripleVis[next.r][next.b][next.y]) { q.offer(next); nodeTripleVis[next.r][next.b][next.y] = true; } } for (Edge e: nodes[curr.y].adjX) { Triple next = new Triple(curr.r, curr.b, e.v); if (!nodeTripleVis[next.r][next.b][next.y]) { q.offer(next); nodeTripleVis[next.r][next.b][next.y] = true; } } // Move red robot along red edges. for (Edge e: nodes[curr.r].adjR) { Triple next = new Triple(e.v, curr.b, curr.y); if (!nodeTripleVis[next.r][next.b][next.y]) { q.offer(next); nodeTripleVis[next.r][next.b][next.y] = true; } edgeVis[e.id] = true; } // Move blue robot along blue edges. for (Edge e: nodes[curr.b].adjB) { Triple next = new Triple(curr.r, e.v, curr.y); if (!nodeTripleVis[next.r][next.b][next.y]) { q.offer(next); nodeTripleVis[next.r][next.b][next.y] = true; } edgeVis[e.id] = true; } // Move yellow robot along yellow edges. for (Edge e: nodes[curr.y].adjY) { Triple next = new Triple(curr.r, curr.b, e.v); if (!nodeTripleVis[next.r][next.b][next.y]) { q.offer(next); nodeTripleVis[next.r][next.b][next.y] = true; } edgeVis[e.id] = true; } if (curr.r==curr.b) { // Move red and blue along purple edges. for (Edge e: nodes[curr.r].adjP) { Triple next = new Triple(e.v, e.v, curr.y); if (!nodeTripleVis[next.r][next.b][next.y]) { q.offer(next); nodeTripleVis[next.r][next.b][next.y] = true; } edgeVis[e.id] = true; } } if (curr.r==curr.y) { // Move red and yellow along orange edges. for (Edge e: nodes[curr.r].adjO) { Triple next = new Triple(e.v, curr.b, e.v); if (!nodeTripleVis[next.r][next.b][next.y]) { q.offer(next); nodeTripleVis[next.r][next.b][next.y] = true; } edgeVis[e.id] = true; } } if (curr.b==curr.y) { // Move blue and yellow along green edges. for (Edge e: nodes[curr.b].adjG) { Triple next = new Triple(curr.r, e.v, e.v); if (!nodeTripleVis[next.r][next.b][next.y]) { q.offer(next); nodeTripleVis[next.r][next.b][next.y] = true; } edgeVis[e.id] = true; } } } for (int i=0; i adjX; ArrayList adjR; ArrayList adjB; ArrayList adjY; ArrayList adjO; ArrayList adjP; ArrayList adjG; public Node(int idd) { id = idd; adjX = new ArrayList(); adjR = new ArrayList(); adjB = new ArrayList(); adjY = new ArrayList(); adjO = new ArrayList(); adjP = new ArrayList(); adjG = new ArrayList(); } } class Edge { int id; int u,v; char c; public Edge(int idd, int uu, int vv, char cc) { id = idd; u = uu; v = vv; c = cc; } } class Triple { int r,b,y; public Triple(int rr, int bb, int yy) { r = rr; b = bb; y = yy; } public int hashCode() { return Objects.hash(r,b,y); } public boolean equals(Object o) { Triple t2 = (Triple)o; return r==t2.r && b==t2.b && y==t2.y; } }