#include <bits/stdc++.h>
using namespace std;
int cs = 1;
struct debugger {
  template <typename T>
  debugger& operator,(const T& v) {
    cerr << v << "\t";
    return *this;
  }
} dbg;
template <class A, class B>
ostream& operator<<(ostream& o, const pair<A, B>& p) {
  return o << "(" << p.first << ", " << p.second << ")";
}
template <class T>
ostream& operator<<(ostream& o, const vector<T>& v) {
  o << "[";
  for (__typeof((v).end()) it = (v).begin(); it != (v).end(); ++it)
    o << *it << ", ";
  return o << "]";
}
template <class T>
ostream& operator<<(ostream& o, const set<T>& v) {
  o << "[";
  for (__typeof((v).end()) it = (v).begin(); it != (v).end(); ++it)
    o << *it << ", ";
  return o << "]";
}
template <class T>
inline void MAX(T& a, T b) {
  if (a < b) a = b;
}
template <class T>
inline void MIN(T& a, T b) {
  if (a > b) a = b;
}
template <class T>
inline bool read(T& x) {
  int c = getchar();
  int sgn = 1;
  while (~c && c < '0' || c > '9') {
    if (c == '-') sgn = -1;
    c = getchar();
  }
  for (x = 0; ~c && '0' <= c && c <= '9'; c = getchar()) x = x * 10 + c - '0';
  x *= sgn;
  return ~c;
}
long long toInt(string s) {
  long long r = 0;
  istringstream sin(s);
  sin >> r;
  return r;
}
string toString(long long number) {
  stringstream second;
  second << number;
  return second.str();
}
vector<string> Split(string s) {
  vector<string> ret;
  istringstream second(s);
  string tisValiden;
  while (second >> tisValiden) ret.push_back(tisValiden);
  return ret;
}
long long BigMod(long long b, long long p, long long m) {
  long long ret = 1;
  while (p) {
    if (p & 1) ret = (ret * b) % m;
    p >>= (1ll), b = (b * b) % m;
  }
  return ret;
}
string i2b(long long a) {
  string s;
  do {
    s += (a & 1) + '0', a >>= 1;
  } while (a);
  reverse(s.begin(), s.end());
  return s;
}
long long GCD(long long a, long long b) {
  while (b) b ^= a ^= b ^= a %= b;
  return a;
}
const int MX_E = 1e6 + 7;
const int MX = 1010;
int N, M, K, W, par[MX_E];
pair<int, int> edges[MX_E];
vector<int> e[MX];
int mat[MX][MX];
char g[MX][15][15];
int Parent(int i) {
  if (i == par[i]) return i;
  return (par[i] = Parent(par[i]));
}
void makeUnion(int a, int b) { par[Parent(b)] = Parent(a); }
bool cmp(pair<int, int> a, pair<int, int> b) {
  return mat[a.first][a.second] < mat[b.first][b.second];
}
vector<pair<int, int> > Ans;
long long Tot = 0;
void dfs(int x, int pre) {
  if (pre != -1) {
    Tot += mat[x][pre];
    Ans.push_back(make_pair(x, pre));
  }
  for (__typeof((e[x]).end()) it = (e[x]).begin(); it != (e[x]).end(); ++it)
    if (*it != pre) dfs(*it, x);
}
int main() {
  for (__typeof((MX_E - 7) - 1) i = (0); i <= (MX_E - 7) - 1; ++i) par[i] = i;
  cin >> N >> M >> K >> W;
  for (__typeof((K)-1) i = (0); i <= (K)-1; ++i)
    for (__typeof((N)-1) j = (0); j <= (N)-1; ++j)
      for (__typeof((M)-1) k = (0); k <= (M)-1; ++k) cin >> g[i][j][k];
  for (__typeof((K)-1) i = (0); i <= (K)-1; ++i) {
    int ret = 1e8;
    for (__typeof((i)-1) j = (0); j <= (i)-1; ++j) {
      int tot = N * M;
      for (__typeof((N)-1) k = (0); k <= (N)-1; ++k)
        for (__typeof((M)-1) l = (0); l <= (M)-1; ++l)
          if (g[i][k][l] == g[j][k][l]) --tot;
      mat[i + 1][j + 1] = mat[j + 1][i + 1] = W * tot;
    }
    mat[i + 1][0] = mat[0][i + 1] = N * M;
  }
  int mxE = 0;
  for (__typeof((K + 1) - 1) i = (0); i <= (K + 1) - 1; ++i)
    for (__typeof(K) j = (i + 1); j <= K; ++j) edges[mxE++] = make_pair(i, j);
  sort(edges, edges + mxE, cmp);
  for (__typeof((mxE)-1) i = (0); i <= (mxE)-1; ++i) {
    int a = edges[i].first, b = edges[i].second;
    if (Parent(a) != Parent(b)) {
      makeUnion(a, b);
      e[a].push_back(b);
      e[b].push_back(a);
    }
  }
  dfs(0, -1);
  cout << Tot << endl;
  for (__typeof((Ans).end()) i = (Ans).begin(); i != (Ans).end(); ++i)
    cout << i->first << " " << i->second << endl;
}
