public static void solveOne() throws Exception { int n = nextInt(); int m = nextInt(); int k = nextInt(); int w = nextInt(); char[][][] levels = new char[k][n][]; ; for (int i = 0; i < k; i++) { for (int j = 0; j < n; j++) { levels[i][j] = nextString().toCharArray(); } } int[][] cost = new int[k][k]; PriorityQueue<int[]> q = new PriorityQueue<>( k * k, new Comparator<int[]>() { @Override public int compare(int[] o1, int[] o2) { return o1[2] - o2[2]; } }); for (int i = 0; i < k; i++) { for (int j = i + 1; j < k; j++) { int[] cur = {i, j, diff(levels[i], levels[j]) * w}; cost[i][j] = cur[2]; q.add(cur); // px("edge", cur); } } // px(q.size()); // for (int[] e: cost) px(e); DisjointUnionSet djs = new DisjointUnionSet(k); boolean[][] al = new boolean[k][k]; int finalCost = n * m * k; for (; q.size() > 0; ) { int[] edge = q.poll(); int p1 = djs.getPartitionId(edge[0]); int p2 = djs.getPartitionId(edge[1]); // px(edge, p1 == p2, edge[2]); if (edge[2] > n * m) break; if (p1 != p2) { djs.unionElement(edge[0], edge[1]); finalCost -= n * m - edge[2]; al[edge[1]][edge[0]] = true; al[edge[0]][edge[1]] = true; } } // for (boolean[] e: al) px(e); pn(finalCost); boolean[] ex = new boolean[k]; for (int i = 0; i < k; i++) { if (!ex[i]) { dfs(i, -1, ex, k, al); } } }
public static void dfs(int at, int from, boolean[] ex, int k, boolean[][] al) { ex[at] = true; pn((at + 1) + " " + (from + 1)); for (int i = 0; i < k; i++) { if (!ex[i] && al[i][at]) { // px(i, at); dfs(i, at, ex, k, al); } } }