//15852K 485MS G++
//http://contest.felk.cvut.cz/03prg/solved/#h
#include <cstdio>
#include <queue>
#include <functional>
#include <cstring>
using namespace std;
#define TRUNK_MAX 2010
#define TRUNK_CODE 10
#define TRUNK_CODE_MAX 7
char trunkInfo[TRUNK_MAX][TRUNK_CODE];
int trunkDistance[TRUNK_MAX][TRUNK_MAX];
// struct TrunkDerivation {
// int begin;
// int end;
// int distance;
// };
typedef struct TrunkDerivation TrunkDerivation;
// class MyCmp {
// public:
// bool operator() (const TrunkDerivation & p1, const TrunkDerivation & p2) {
// return p1.distance > p2.distance;
// }
// };
// priority_queue<TrunkDerivation, std::vector<TrunkDerivation>, MyCmp> edgeQueue;
int truckNum;
int nodeFlag[TRUNK_MAX];
int key[TRUNK_MAX];
#define INF 999999
int getDistance(char *p1, char *p2) {
int res = 0;
for (int i = 0; i < TRUNK_CODE_MAX; i++) {
if (p1[i] != p2[i]) {
res++;
}
}
return res;
}
int Prim() {
// while(edgeQueue.size()) {
// edgeQueue.pop();
// }
int distanceSum = 0;
// nodeFlag[0] = 1; // add 1 in V1
int newEnd;
int newDistance = 99999;
for (int i = 0; i < truckNum; i++) {
key[i] = INF;
}
key[0] = 0;
int leftNode = truckNum;
while (leftNode) {
int minId = -1;
int minKey = INF;
for (int i = 0; i < truckNum; i++) {
if (minKey > key[i] && !nodeFlag[i]) {
minKey = key[i];
minId = i;
}
}
nodeFlag[minId] = 1;
// if (minKey != INF) {
distanceSum += minKey;
// }
for (int i = 0; i < truckNum; i++) {
// printf("1 %d %d %d %d\n", minId, i,
// trunkDistance[minId][i], key[i]);
if (!nodeFlag[i] && trunkDistance[minId][i] > 0) {
if (trunkDistance[minId][i] < key[i]) {
// printf("%d %d %d %d\n", minId, i,
// trunkDistance[minId][i], key[i]);
key[i] = trunkDistance[minId][i];
}
}
}
leftNode--;
}
return distanceSum;
}
int solve() {
for (int i = 0; i < truckNum; i++) {
for (int j = i; j < truckNum; j++) {
if (i == j) {
trunkDistance[i][j] = -1;
} else {
trunkDistance[i][j] = getDistance(trunkInfo[i], trunkInfo[j]);
trunkDistance[j][i] = trunkDistance[i][j];
}
}
}
int minQulity = Prim();
printf("The highest possible quality is 1/%d.\n", minQulity);
}
int main() {
while(1) {
scanf("%d", &truckNum);
if (truckNum == 0) {
return 0;
}
memset(trunkInfo, 0, sizeof(trunkInfo));
memset(nodeFlag, 0, sizeof(nodeFlag));
for (int i = 0; i < truckNum; i++) {
scanf("%s", trunkInfo[i]);
}
solve();
}
}
考察prim算法的基本题。没啥可说的。
一开始把prim给记错了,贡献了几次WA。
算导上的prim用的是优先级队列,不过因此STL提供的优先级队列不会自动调整(即只有push或者pop了元素才会重新调整队列,但是算导中的则要求
队列中某个元素改变也要能触发重现调整,自己写一个小顶堆其实就可以满足需求,不过懒得写了),因此就直接用比较费时的
每次遍历所有元素来找到最小的边, 不过也能满足该题的需求了。