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;
}

 

posted @ 2014-03-21 00:11  辛力啤  阅读(184)  评论(0编辑  收藏  举报