最小生成树--Truck History(poj 1789);

来源:互联网 发布:管理数据分析 编辑:程序博客网 时间:2024/06/14 11:25
卡车历史
时限:2000MS 内存限制:65536K
提交材料共计: 30032 接受: 11735
描述


先进货运有限公司使用不同类型的卡车。有些卡车用于蔬菜运送,其他用于家具或砖。该公司有自己的代码描述每种类型的卡车。该代码只是一个由七个小写字母组成的字符串(每个位置上的每个字母都有一个非常特殊的含义,但对于这个任务并不重要)。在公司发展的初期,只使用了一种卡车类型,后来又衍生出其他类型的卡车,然后从新的类型中衍生出另一种类型,等等。


今天,ACM已经足够富有,足以让历史学家们去研究它的历史了。有一件事是历史学家试图找出的,那就是所谓的派生计划-即如何派生出卡车类型。他们把卡车类型的距离定义为卡车类型代码中不同字母的位置数。他们还认为,每种卡车类型都是从另外一辆卡车中派生出来的(第一种卡车类型除外,它不是从任何其他类型衍生出来的)。然后将派生计划的质量定义为
                              1/Σ(to,td)d(to,td)


其中,求和在派生计划中对所有类型的类型进行处理,使tO是原始类型和td派生自它和d(T0,td)的类型是类型的距离。
因为历史学家失败了,你要写一个计划来帮助他们。给定卡车类型的代码,您的程序应该找到派生计划的最高质量。
输入


输入由几个测试用例组成。每个测试用例以一个包含卡车类型数量的直线开始,n,2<=n<=2 000。下面的每个输入行都包含一个卡车类型代码(一个由七个小写字母组成的字符串)。您可以假设代码唯一地描述了卡车,也就是说,这些N中没有两个是相同的。输入在卡车类型的数目处以零结束。
输出


对于每个测试用例,您的程序应该输出文本“The highest possible quality is1/q”,其中1/q是最佳派生计划的质量。
样本输入


4
aaaaaaa
baaaaaa
abaaaaa

aabaaaa

 0

样本输出


The highest possible quality is 1/3.

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

例如有如下4个编号:

aaaaaaa

baaaaaa

abaaaaa

aabaaaa

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

问题可以转化为最小代价生成树的问题。因为每两个结点之间都有路径,所以是完全图。 

此题的关键是将问题转化为最小生成树的问题。每一个编号为图的一个顶点,顶点与顶点间的编号差即为这条边的权值,题目所要的就是我们求出最小生成树来。这里我用prim算法来求最小生成树。


#include <iostream>#include <cstdio>#include <queue>#include <cstring>#define NUM 2002using namespace std;int Graph[NUM][NUM];int N;//顶点数;char str[NUM][8];struct node     //保存key值的结点{    int v;    int key;    friend bool operator<(node a, node b)   //自定义优先级,key小的优先    {    return a.key > b.key;    }};int parent[NUM];   //每个结点的父节点bool visited[NUM]; //是否已经加入树种node vx[NUM];      //保存每个结点与其父节点连接边的权值priority_queue<node> q; //优先队列stl实现、、将排序的功能用其来实现;//将自动的按照相应的排序方式排序void Prim(){    for(int i = 1; i <= N; i++) //初始化        {        vx[i].v = i;        vx[i].key = 1<<30;        parent[i] = -1;        visited[i] = false;        }    vx[1].key = 0;    q.push(vx[1]);    while(!q.empty())        {        node nd = q.top();  //取队首,记得赶紧pop掉        q.pop();        if(visited[nd.v] == true)   //深意,因为push机器的可能是重复但是权值不同的点,我们只取最小的            continue;        int st = nd.v;        visited[nd.v] = true;        for(int j = 1;  j <= N; j++)            {            if(j!=st && !visited[j] && Graph[st][j] < vx[j].key)    //判断                {                parent[j] = st;                vx[j].key = Graph[st][j];                q.push(vx[j]);                }            }        }}int main(){    while(scanf("%d",&N)&&N!=0){        for(int i = 1;i<=N;i++)            scanf("%s",str[i]);        memset(Graph, 124,sizeof(Graph));        for(int  i= 1;i<=N;i++)            for(int j = i+1;j<=N;j++){                int w = 0;                for(int k = 0;k<7;k++)                    if(str[i][k]!=str[j][k])                        w++;                Graph[j][i] = Graph[i][j] = w;            }        Prim();        int ans = 0;        for(int i = 1;i<=N;i++)            ans+=vx[i].key;        printf("The highest possible quality is 1/%d.\n",ans);    }    return 0;}



原创粉丝点击