MST....
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
struct Edge
{
int u,v,w;
}edge[1100*1100];
bool cmp(Edge a,Edge b)
{
return a.w<b.w;
}
int n,m,k,w;
int fa[1100],diff[1100][1100];
char ch[1100][20][20];
vector<int> vc[1100];
int get_diff(char a[][20],char b[][20] )
{
int ret=0;
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
if(a[i][j]!=b[i][j])
ret++;
}
}
return ret;
}
int getfa(int x)
{
if(x==fa[x]) return x;
else return fa[x]=getfa(fa[x]);
}
int kruscal(int eg)
{
sort(edge,edge+eg,cmp);
for(int i=0;i<=k+1;i++)
{
fa[i]=i;
vc[i].clear();
}
int cnt=k+1,ans=0;
for(int i=0;i<eg;i++)
{
int f1=getfa(edge[i].u);
int f2=getfa(edge[i].v);
if(f1!=f2)
{
fa[f1]=f2;
ans+=edge[i].w;
vc[edge[i].u].push_back(edge[i].v);
vc[edge[i].v].push_back(edge[i].u);
cnt--;
if(cnt==1) break;
}
}
return ans;
}
void dfs(int u,int fa)
{
for(int i=0,sz=vc[u].size();i<sz;i++)
{
int v=vc[u][i];
if(v==fa) continue;
printf("%d %d\n",v,u);
dfs(v,u);
}
}
int main()
{
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",ch[i][j]);
}
}
for(int i=1;i<=k;i++)
{
for(int j=i+1;j<=k;j++)
{
diff[j][i]=diff[i][j]=get_diff(ch[i],ch[j])*w;
}
}
int eg=0;
for(int i=1;i<=k;i++)
{
edge[eg++]=(Edge){0,i,n*m};
for(int j=i+1;j<=k;j++)
{
edge[eg++]=(Edge){i,j,diff[i][j]};
}
}
printf("%d\n",kruscal(eg));
dfs(0,0);
return 0;
}