import java.util.*; import java.io.*; public class rainbowgraph_font { public static void main(String[] args) throws Exception { PrintWriter out = new PrintWriter(System.out); new rainbowgraph_font(new FastScanner(System.in), out); out.close(); } int N, M, oo = 987654321; Edge[] edges; // Add the connection if removing some edge and replacing it maintains // connectivity. Graph buildExchange(boolean[] includedEdges, int color) { Graph g = new Graph(M); for (int i=0; i 0 && ds.find(e.i) != ds.find(e.j)) { g.add(j, i); } } } includedEdges[i] = true; } } return g; } // Modify includeEdges to be the new edges in the current solution set // Run one step of the matroid intersection algorithm. boolean augment(boolean[] includedEdges) { // Build a connection graph Graph g = buildExchange(includedEdges, 1); Graph g2 = buildExchange(includedEdges, 2); g.mergeInto(g2.reversed()); // If removing this edge still causes color 1 to be connected, then // this node is a source // Edge must currently be in the graph boolean[] isSource = new boolean[M]; for (int i=0; i 0 && includedEdges[i]) ds.union(edges[i].i, edges[i].j); return ds; } boolean testConnectivity(boolean[] includedEdges, int color) { return getComponents(includedEdges, color).numComps == 1; } boolean isConnected(boolean[] includedEdges) { return testConnectivity(includedEdges, 1) && testConnectivity(includedEdges, 2); } int getCost(boolean[] includedEdges) { int res = 0; for (int i=0; i=1; numEdges--) { res[numEdges] = getCost(includedEdges); if (!augment(includedEdges)) break; if (!isConnected(includedEdges)) { System.out.println("BADNESS"); break; } } for (int u=1; u<=M; u++) out.println(res[u]); } } class Edge { int i, j, w; int color; Edge(int ii, int jj, int ww, int cc) { i=ii; j=jj; w=ww; color=cc; } } class DisjointSet { int numComps; int[] p, r; DisjointSet(int s) { p = new int[s]; r = new int[s]; for(int i=0; i[] adj; Graph(int NN) { adj = new ArrayList[N=NN]; for (int i=0; i(); } void add(int i, int j) { adj[i].add(j); } Graph reversed() { Graph rev = new Graph(N); for (int i=0; i= numChars){ curChar = 0; try{ numChars = stream.read(buf); } catch (IOException e) { throw new InputMismatchException(); } if (numChars <= 0) return -1; } return buf[curChar++]; } boolean isSpaceChar(int c) { return c==' '||c=='\n'||c=='\r'||c=='\t'||c==-1; } boolean isEndline(int c) { return c=='\n'||c=='\r'||c==-1; } int nextInt() { return Integer.parseInt(next()); } long nextLong() { return Long.parseLong(next()); } double nextDouble() { return Double.parseDouble(next()); } String next(){ int c = read(); while (isSpaceChar(c)) c = read(); StringBuilder res = new StringBuilder(); do{ res.appendCodePoint(c); c = read(); }while(!isSpaceChar(c)); return res.toString(); } String nextLine(){ int c = read(); while (isEndline(c)) c = read(); StringBuilder res = new StringBuilder(); do{ res.appendCodePoint(c); c = read(); }while(!isEndline(c)); return res.toString(); } }