/*
* 很直接的最小生成树
*
* 版本一: Kruskal, 链表实现
*
*/
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxN = 2000 + 5;
const int letterNum = 7;
int n, totEdgeNum, ans;
char code[maxN][letterNum + 2];
struct SEdge{ //边
int w, u, v;
};
SEdge edge[maxN * maxN];
struct SNode{ //链表的节点
SNode *rep, *next;
int num;
};
SNode *head[maxN], *tail[maxN], *node[maxN];
SNode *makeSet(SNode *x){
head[x->num] = x;
tail[x->num] = x;
x->rep = x; x->next = NULL;
return x;
}
SNode *findSet(SNode *x){
return x->rep;
}
//直接把 rhs 连在 lhs 后面
SNode *unionSet(SNode *lhs, SNode *rhs){
SNode *lhsRep = findSet(lhs);
SNode *rhsRep = findSet(rhs);
tail[lhsRep->num]->next = rhsRep;
SNode *tmpNode = rhsRep;
while(tmpNode != NULL){
tmpNode->rep = lhsRep;
tmpNode = tmpNode->next;
}
tail[lhsRep->num] = tail[rhsRep->num];
head[rhsRep->num] = head[lhsRep->num];
return lhsRep;
}
int cmp(const void *lhs, const void *rhs){
SEdge *a = (SEdge *)lhs; SEdge *b = (SEdge *)rhs;
return a->w - b->w;
}
void mstKruskal(){
//初始化
for(int i=0; i<n; i++){
node[i] = new SNode;
node[i]->num = i;
makeSet(node[i]);
}
//边按权值排序
qsort(edge, totEdgeNum, sizeof(SEdge), cmp);
for(int i=0; i<totEdgeNum; i++){
SNode *uRep = findSet(node[edge[i].u]);
SNode *vRep = findSet(node[edge[i].v]);
if(uRep != vRep){
unionSet(uRep, vRep);
ans += edge[i].w;
}
}
}
//计算边的权值
int inline getDistance(char *lhs, char *rhs){
int dis = 0;
for(int i=0; i<letterNum; i++)
if(lhs[i] != rhs[i]) dis++;
return dis;
}
int main(){
while(scanf("%d", &n)){
if(n == 0) return 0;
ans = totEdgeNum = 0;
getchar();
for(int i=0; i<n; i++){
gets(code[i]);
for(int j=0; j<=i; j++){
edge[totEdgeNum].w = getDistance(code[i], code[j]);
edge[totEdgeNum].u = i; edge[totEdgeNum].v = j;
totEdgeNum++;
}
}
mstKruskal();
printf("The highest possible quality is 1/%d.\n", ans);
}
return 0;
}
--
/*
* 很直接的最小生成树
*
* 版本二: Kruskal, 不相交集合森林
*
*/
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxN = 2000 + 5;
const int letterNum = 7;
int n, totEdgeNum, ans;
char code[maxN][letterNum + 2];
struct SEdge{ //边
int w, u, v;
};
SEdge edge[maxN * maxN];
struct SNode{ //链表的节点
SNode *p;
int num, rank;
};
SNode *node[maxN];
SNode *makeSet(SNode *x){
x->p = x;
x->rank = 0;
return x;
}
SNode *findSet(SNode *x){
if(x != x->p)
x->p = findSet(x->p); //路径压缩
return x->p;
}
void link(SNode *lhs, SNode *rhs){
if(lhs->rank > rhs->rank) //按秩合并
rhs->p = lhs;
else{
lhs->p = rhs;
if(lhs->rank == rhs->rank)
rhs->rank++;
}
}
void unionSet(SNode *lhs, SNode *rhs){
link(findSet(lhs), findSet(rhs));
}
int cmp(const void *lhs, const void *rhs){
SEdge *a = (SEdge *)lhs; SEdge *b = (SEdge *)rhs;
return a->w - b->w;
}
void mstKruskal(){
//初始化
for(int i=0; i<n; i++){
node[i] = new SNode;
node[i]->num = i;
makeSet(node[i]);
}
//边按权值排序
qsort(edge, totEdgeNum, sizeof(SEdge), cmp);
for(int i=0; i<totEdgeNum; i++){
SNode *uRep = findSet(node[edge[i].u]);
SNode *vRep = findSet(node[edge[i].v]);
if(uRep != vRep){
unionSet(uRep, vRep);
ans += edge[i].w;
}
}
}
//计算边的权值
int inline getDistance(char *lhs, char *rhs){
int dis = 0;
for(int i=0; i<letterNum; i++)
if(lhs[i] != rhs[i]) dis++;
return dis;
}
int main(){
while(scanf("%d", &n)){
if(n == 0) return 0;
ans = totEdgeNum = 0;
getchar();
for(int i=0; i<n; i++){
gets(code[i]);
for(int j=0; j<=i; j++){
edge[totEdgeNum].w = getDistance(code[i], code[j]);
edge[totEdgeNum].u = i; edge[totEdgeNum].v = j;
totEdgeNum++;
}
}
mstKruskal();
printf("The highest possible quality is 1/%d.\n", ans);
}
return 0;
}