题目大意 读入有N个7位的字符串,定义每个字符串之间的距离是他们之间不同字符的个数,然后就是求最小生成树的水题了
这题用不同方法做了几遍了,废话就不说开了,
只是我第一次写PRIM算法
增点集。。。就是PRIM算法中节点不断增加的点的集合
减点集。。。与增点集相反的点集,其中的点不断减少,直到为零算法就结束了
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<queue>
#include<cstring>
#define INF 1e9
using namespace std;
int closest[2100]; //存的是最短边的在增点集的端点 ,数组的下标表示减集的点的编号
int lowcost[2100];//存最短边的数组,即增点集合的所有的点到数组下标代表的减点集合的点的最短距离
int m;//点的个数
char tu[2105][8];
int cal(int i,int j)//计算2个字串的距离
{
int ans=0,ii=-1;
while(++ii<7)
if(tu[i][ii]!=tu[j][ii])
ans++;
return ans;
}
void read()
{
for(int i=0;i<m;i++)
scanf("%s",tu[i]);
}
void deal()//prim算法
{
for(int i=0;i<m;i++) { lowcost[i]=INF;}//初始化 lowcost数组
for(int i=0;i<m;i++) { closest[i]=0;}//初始化closest 数组 -1表示该点已经被选入增点的集合,否则在检点的集合
closest[0]=-1;//加入第一个点
int num=0,ans=0,e=0;//e代表最新加入增点集的点
while(++num<m)//加入m-1条边
{
int micost=INF,miedge=-1;//micost代表当前的最短边,miedge代表当前最短边在减点集中的端点
for(int i=0;i<m;i++)//更新最短边
if(closest[i]!=-1)//选择减点集的点更新最短距离
{
int temp=cal(e,i);
if(temp<lowcost[i])
{
lowcost[i]=temp;
closest[i]=e;
}
if(lowcost[i]<micost)//更新当前的最短边
micost=lowcost[miedge=i];
}
ans+=micost;
closest[e=miedge]=-1;//加入新的点到减点集,同时更新增点集的点e,最新加入的点e
}
printf("The highest possible quality is 1/%d.\n",ans);
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
while(cin>>m,m)
{
read();
deal();
}
return 0;
}