最小生成树,一次ac(兴奋ing)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct edge
{
int x, y, w;
}e[1001];
const int N = 1e5 + 5,MAX=99999999;
int n, m, k, w;
char s[1001][121]; int dis[1001][1001], low[1001]; edge ee[1001];
int main() {
scanf("%d%d%d%d", &n, &m, &k, &w);
int cnt = 0;
for (int i = 0; i < k; i++)
{
for (int j = 0; j < n; j++)
{
scanf("%s", s[i] + j*m);
}
}
for (int i = 0; i < k; i++)
{
for (int j = i + 1; j < k; j++)
{
for (int l = 0; l < n*m; l++)
{
dis[i+1][j+1] += s[i][l] != s[j][l];
}
dis[i + 1][j + 1] *= w;
dis[j+1][i+1] = dis[i+1][j+1];
}
}
for (int i = 1; i <= k; i++)
{
dis[0][i] = dis[i][0] = n*m;
}
for (int j = 1; j <= k; j++)
{
low[j] = n*m; ee[j] = edge{ j, 0, n*m };
}
int ans = 0;
for (int i = 0; i < k; i++)
{
int index = -1, Min = MAX;
for (int j = 1; j <= k; j++)
{
if (low[j] != -1 && low[j] < Min)
{
Min = low[j];
index = j;
}
}
e[cnt++] = edge{ index, ee[index].y, Min };
low[index] = -1;
ans += Min;
for (int j = 1; j <= k; j++)
{
if (low[j] != -1 && low[j]>dis[index][j])
{
low[j] = dis[index][j];
ee[j].y = index;
ee[j].w = low[j];
}
}
}
printf("%d\n", ans);
for (int i = 0; i < cnt; i++)
{
printf("%d %d\n", e[i].x, e[i].y);
}
return 0;
}