题意:
用一个7为的字符串代表一个卡车的编号,每两个字符串的差异值为它们不同的字母的位数。如:
abaaaaa aabaaaa
的差异值为2,因为他们有两位不同。
每个卡车的编号可以由其他编号变换过来,代价为它们的差异值。
为要生成所有的编号,最小的代价为多少。
思路:
本题可以转化成最小生成树。
每个节点代表一个编号,与其他所有节点连边,权值为代价。
可见,最小生成树即为最小总代价。
代码(25352K,1297MS):
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
struct Edge{
int from, to, v;
Edge(int a, int b, int c) : from(a), to(b), v(c) {}
bool operator < (const Edge &e) const {
return v < e.v;
}
};
int n;
char str[2005][8];
int parent[2005];
vector<Edge> edges;
int find(int p) {
if (p == parent[p]) return p;
return parent[p] = find(parent[p]);
}
void un(int p, int q) {
parent[find(p)] = find(q);
}
int kruskal() {
int siz = edges.size();
int ans = 0;
for (int i = 0; i < siz; i++) {
Edge e = edges[i];
if (find(e.from) != find(e.to)) {
un(e.from, e.to);
ans += e.v;
}
}
return ans;
}
int main() {
while (~scanf("%d", &n) && n) {
for (int i = 0; i <= n; i++)
parent[i] = i;
edges.clear();
for (int i = 0; i < n; i++) {
scanf("%s", str[i]);
for (int j = 0; j < i; j++) {
int v = 0; // 代价
for (int k = 0; k < 7; k++)
if (str[i][k] != str[j][k]) v++;
edges.push_back(Edge(i, j, v));
}
}
sort(edges.begin(), edges.end());
int ans = kruskal();
printf("The highest possible quality is 1/%d.\n", ans);
}
return 0;
}