#include <bits/stdc++.h>
using namespace std;
struct road {
  int x, y, cost;
};
struct comp {
  bool operator()(struct road x, struct road y) { return x.cost > y.cost; }
};
int head[1005];
int uf[1005];
bool mark[1005];
vector<int> tree[1005];
priority_queue<road, vector<road>, comp> heap;
char level[1005][11][11];
void dfs(int n) {
  for (int i = 0; i < tree[n].size(); i++) {
    if (!mark[tree[n][i]]) {
      printf("%d %d\n", tree[n][i], n);
      mark[tree[n][i]] = true;
      dfs(tree[n][i]);
    }
  }
}
int findhead(int i) {
  if (i != uf[i]) uf[i] = findhead(uf[i]);
  return uf[i];
}
int main() {
  int n, m, k, w, dif;
  struct road e;
  scanf("%d %d %d %d", &n, &m, &k, &w);
  for (int i = 1; i <= k; i++) {
    for (int j = 0; j < n; j++) {
      scanf("%s", level[i][j]);
    }
  }
  for (int i = 1; i < k; i++) {
    for (int j = i + 1; j <= k; j++) {
      dif = 0;
      for (int l = 0; l < n; l++) {
        for (int o = 0; o < m; o++) {
          if (level[i][l][o] != level[j][l][o]) {
            dif++;
          }
        }
      }
      dif *= w;
      e.x = i;
      e.y = j;
      e.cost = dif;
      heap.push(e);
    }
  }
  for (int i = 1; i <= k; i++) {
    e.x = 0;
    e.y = i;
    e.cost = n * m;
    heap.push(e);
  }
  for (int i = 0; i <= k; i++) {
    uf[i] = i;
  }
  int sm = 0;
  for (int i = 1; i <= k; i++) {
    while (true) {
      e = heap.top();
      heap.pop();
      if (findhead(e.x) != findhead(e.y)) {
        uf[uf[e.x]] = uf[e.y];
        sm += e.cost;
        tree[e.x].push_back(e.y);
        tree[e.y].push_back(e.x);
        break;
      }
    }
  }
  mark[0] = true;
  printf("%d\n", sm);
  dfs(0);
}
