poj1789

最小生成树问题:(prim算法)

/*题意大概是这样的:用一个7位的string代表一个编号,两个编号之间的distance代表这两个编号之间不同字母的个数。
一个编号只能由另一个编号“衍生”出来,代价是这两个编号之间相应的distance,现在要找出一个“衍生”方案,使得
总代价最小,也就是distance之和最小。 
 例如有如下4个编号:
 
   aaaaaaa
   baaaaaa
   abaaaaa
   aabaaaa
   显然的,第二,第三和第四编号分别从第一编号衍生出来的代价最小,因为第二,第三和第四编号分别与第一编号
   只有一个字母是不同的,相应的distance都是1,加起来是3。也就是最小代价为3.
*/

#include <iostream>
#define MAX 2005
using namespace std;
char str[MAX][7];
bool visit[MAX];//标记数组,没有加入到树中时为false,加入了为true
int distan[MAX];//用以记录当前树到各个顶点的最小距离(它会被不断的更新,加入一个顶点更新一次)
int n;
int dist(char *str1,char *str2)//计算两个顶点之间的权值
{
int d=0;
for(int i=0;i<7;i++)
if(str1[i]!=str2[i])
++d;
return d;
}

int prim()//prim算法
{
int v,i,j,sum=0;
visit[
0]=true;//将第一个顶点加入树中
for(i=0;i<n;i++)//计算只有一个顶点时的distan[i]
distan[i]=dist(str[0],str[i]);

for(j=1;j<n;j++)
{
int mini=9;
for (i=0;i<n;i++)//找最小的边
{
if(visit[i]==false&&distan[i]<mini)//找出没有在当前树中且权值最小的点
{
mini
=distan[i];
v
=i;
}
}
visit[v]
=true;//标记顶点v,加入生成树中
sum+=mini;
for (i=0;i<n;i++)//将生成树的权值更新
{
int k=dist(str[v],str[i]);
if(visit[i]==false&&distan[i]>k)//distan[i]中始终放生成树到顶点i的最小权值
{
distan[i]
=k;
}
}
}
return sum;
}

int main()
{
int i;
while(cin>>n&&n)
{
for(i=0;i<n;i++)
{cin
>>str[i];visit[i]=false;}
cout
<<"The highest possible quality is 1/"<<prim()<<'.'<<endl;
}
return 0;
}

你可能感兴趣的:(poj)