POJ 1789 Truck History
这个题是一个最小生成树的题,题意如下:
1、每一种卡车的类型是由7个字母表示的。
2、每一种卡车的类型是由其他某一种卡车的类型衍生的(第一种除外)。
3、某两种卡车之间衍生的代价是由这两种卡车所代表的字符串的字母不同的个数表示的。
4、求怎样衍生代价最小。
这是一个稠密图最小生成树题,用Prim算法比较好,因为POJ数据较水,Kruskal也不会超时。但是如果真出现2000种卡车的情况,4000000条边,超时妥妥的。
下面是代码:
#include <stdio.h> #include <string.h> const int M=2005; char s[M][10]; int map1[M][M],n; #define typec int // type of cost const typec inf = 0x3f3f3f3f; // max of cost int vis[M]; typec lowc[M]; typec prim(typec cost[][M]) // vertex: 0 ~ n-1 { int i, j, p; typec minc, res = 0; memset(vis, 0, sizeof(vis)); vis[0] = 1; for (i=1; i<n; i++) lowc[i] = cost[0][i]; for (i=1; i<n; i++) { minc = inf; p = -1; for (j=0; j<n; j++) if (0 == vis[j] && minc > lowc[j]) { minc = lowc[j]; p = j; } if (inf == minc) return -1; // 原图不连通 res += minc; vis[p] = 1; for (j=0; j<n; j++) if (0 == vis[j] && lowc[j] > cost[p][j]) lowc[j] = cost[p][j]; } return res; } int findl(int a,int b) { int cut=0,i; for(i=0; i<7; i++) { if(s[a][i]!=s[b][i]) { cut++; } } return cut; } int main() { int i,j; while(scanf("%d",&n),n) { for(i=0; i<n; i++) { scanf("%s",s[i]); } for(i=0; i<n; i++) { for(j=0; j<n; j++) { map1[i][j]=findl(i,j); } } printf("The highest possible quality is 1/%d.\n",prim(map1)); } return 0; }