poj 1789 最小生成树 prim
/* 题意:题目很长很坑爹很难理解,就是每种卡车都由特定的7个字母组成的代码表示,而且每种卡车都是由 其它种类的卡车衍生而来(除了初始的那辆祖先卡车);从卡车a衍生到卡车b,它们的distance为两种卡车代 码的相应位置字母不同的数目,现在给出n种卡车,保证代码都不同,两两之间既可能a衍生到b,也可能b衍 生到a;求出其中一种情况使得从其中某辆车衍生出所有其它车,并且使所有distance值之和最小。 题解:最小生成树,prim算法; 每种车都只能由一种车衍生而来,只有初始的那辆为祖先,很明显构成了一颗树,只有根结点没有前驱,其 余结点都只有一个父结点,给出的所有卡车两两相互连接构成一个无向图,边值为distance,显然是从无向 图中找出最小生成树。 */ #include <cstdio> #include <cstring> using namespace std; int map[2005][2005]; char s[2005][10]; int prim(int n) { int from,min,sum=0; bool vis[2005]; int low[2005]; memset(vis,false,sizeof(vis)); vis[0] = true; from = 0; for(int i=0; i<n; i++) low[i] = map[from][i]; for(int i=1; i<n; i++) { min = 20; for(int j=0; j<n; j++) { if (!vis[j] && low[j]<min) { min = low[j]; from = j; } } sum += min; vis[from] = true; for(int j=0; j<n; j++) { int t = map[from][j]; if (!vis[j] && low[j]>t) low[j] = t; } } return sum; } int main(void) { int n; while (~scanf("%d",&n) && n) { memset(map,0,sizeof(map)); scanf("%*c"); for(int i=0; i<n; i++) { for(int j=0; j<7; j++) scanf("%c",&s[i][j]); scanf("%*c"); } for(int i=0; i<n; i++) { for(int j=0; j<n; j++) { if (i != j) { for(int k=0; k<7; k++) if (s[i][k] != s[j][k]) map[i][j]++; } } } printf("The highest possible quality is 1/%d.\n",prim(n)); } return 0; }