poj1789 Truck History(Prim算法实现)

来源:互联网 发布:共享单车大数据 编辑:程序博客网 时间:2024/05/22 15:38

poj1789 Truck History

题意大概是这样的:用一个7位的string代表一个编号,两个编号之间的distance代表这两个编号之间不同字母的个数。一个编号只能由另一个编号“衍生”出来,代价是这两个编号之间相应的distance,现在要找出一个“衍生”方案,使得总代价最小,也就是distance之和最小。

例如有如下4个编号:

aaaaaaabaaaaaaabaaaaaaabaaaa

显然的,第二,第三和第四编号分别从第一编号衍生出来的代价最小,因为第二,第三和第四编号分别与第一编号只有一个字母是不同的,相应的distance都是1,加起来是3。也就是最小代价为3。

问题可以转化为最小代价生成树的问题。因为每两个结点之间都有路径,所以是完全图。首先考虑用Kruskal算法解题,配合Disjoint Set Forest可以达到O(E lgV)。可是最后却无情的TLE了。分析TLE原因,原来K算法需要对所有边进行一次排序,当边数目比较多时,这就是非常耗时的一个工作。尤其本题是完全图,其代价可想而知。

 具体实现如下:

#include <stdio.h>
#define SIZE 2012
int map[SIZE][SIZE];
char code[SIZE][10];

int main(){
    int N;
    int i,j,k,ans,diff,count,min,indexj;
    int lowedge[SIZE];
    while(scanf("%d",&N),N!=0){
        //建图
        for(i=0;i<N;i++)
            scanf("%s",code[i]);
        for(i=0;i<N;i++){
            for(j=i;j<N;j++)
            {
                diff=0;
                for(k=0;k<7;k++)
                    if(code[i][k]!=code[j][k]) diff++;
                map[i][j]=map[j][i]=diff;
            }
        }
   /* for(i=0;i<N;i++)
    {
        for(j=0;j<N;j++)
            printf("%d  ",map[i][j]);
        printf("\n");
    }
    printf("Input Successs!\n");*/

    ans=0;
    //初始化flag[SIZE],adjacent[SIZE]
    for(i=0;i<N;i++)
    {
        lowedge[i]=map[0][i];
        //printf("%d ",lowedge[i]);
    }
    //printf("\n");
    lowedge[0]=0;
    count=N;
    while(--count){
    min=999;
    for(j=0;j<N;j++)
        if(lowedge[j]!=0&&lowedge[j]<min)
        {   //edge[i]=0表示加入了TE中
            min=lowedge[j];
            indexj=j;
        }
    //printf("min=%d\n",min);
    ans+=lowedge[indexj];
    lowedge[indexj]=0;

    for(j=0;j<N;j++)
        if(lowedge[j]!=0&&map[indexj][j]<lowedge[j])
           lowedge[j]=map[indexj][j];
    /*printf("修改后的lowedge[i]:\n");
    for(i=0;i<N;i++)
        printf("%d ",lowedge[i]);
    printf("\n");*/
    }
    printf("The highest possible quality is 1/%d.\n",ans);
    }
    return 0;
}