poj 1789 Truck History 最小生成树

来源:互联网 发布:兰里岛之战 鳄鱼 知乎 编辑:程序博客网 时间:2024/05/16 14:33
Truck History
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 16565 Accepted: 6364

Description
Advanced Cargo Movement, Ltd. uses trucks of different types. Some trucks are used for vegetable delivery, other for furniture, or for bricks. The company has its own code describing each type of a truck. The code is simply a string of exactly seven lowercase letters (each letter on each position has a very special meaning but that is unimportant for this task). At the beginning of company's history, just a single truck type was used but later other types were derived from it, then from the new types another types were derived, and so on.

Today, ACM is rich enough to pay historians to study its history. One thing historians tried to find out is so called derivation plan -- i.e. how the truck types were derived. They defined the distance of truck types as the number of positions with different letters in truck type codes. They also assumed that each truck type was derived from exactly one other truck type (except for the first truck type which was not derived from any other type). The quality of a derivation plan was then defined as
1/Σ(to,td)d(to,td)

where the sum goes over all pairs of types in the derivation plan such that to is the original type and td the type derived from it and d(to,td) is the distance of the types.
Since historians failed, you are to write a program to help them. Given the codes of truck types, your program should find the highest possible quality of a derivation plan.

Input
The input consists of several test cases. Each test case begins with a line containing the number of truck types, N, 2 <= N <= 2 000. Each of the following N lines of input contains one truck type code (a string of seven lowercase letters). You may assume that the codes uniquely describe the trucks, i.e., no two of these N lines are the same. The input is terminated with zero at the place of number of truck types.

Output
For each test case, your program should output the text "The highest possible quality is 1/Q.", where 1/Q is the quality of the best derivation plan.

Sample Input

4
aaaaaaa
baaaaaa
abaaaaa
aabaaaa
0

Sample Output

The highest possible quality is 1/3.

======================================================================================

题目大意:说有个卡车厂生产各种型号的卡车,每个型号有一串7个小写字母组成的型号代码,型号代码都是独一无二的。最早这个厂只有一个型号代码,后来每把一串代码中的若干字母换掉就得到一个新的独特的代码。题目定义了两个代码之间的距离:两个代码之间各位不同的字母数。又定义了获取代码的密度:1/∑(每获取一次代码时新旧代码的距离)。求这个密度最大为多少,也就是求距离和最小是多少。


解题思路:一个代码看成一个点的话,代码之间互相派生而成,代码由代码间的距离连接成一棵生成树。那么我们要求的正是最小生成树的边权和。这道题提供的条件是所有代码两两之间的距离,也就是说,是一个填满邻接矩阵的稠密图。正好我们来比较一下稠密图中Prim和Kruskal的效率。

Prim:

//Memory: 15784KTime: 407MS#include<cstdio>const int INF = 8;               //边权值不超过7const int N = 2000;              //最多可达2000个点char t[N][8];int g[N][N] , n;                 //建立邻接矩阵int closestV[N];                 //closestV表示点状态和距离最近的点int lowCost[N];                  //存储连边中的最小权值,跟closestV                                 //一起描述每个点与邻接点的关系//Prim算法int Prim(){    //初始化    int selectVNum = 1;    int ans = 0;    int newV = 0;                //将点0作为新选中的点    for( int i = 0 ; i < n ; i++ )        closestV[i] = 0;         //最近点都先指向起点等待更新    closestV[0] = -1;            //closestV[i]=-1表示选中点i    for( int i = 0 ; i < n ; i++ )        lowCost[i] = INF;        //连边最小权值置为无限等待更新    //扩展选中点集    while(selectVNum < n)    {        int minCost = INF , VtoAdd;        for( int i = 0 ; i < n ; i++ )            if(closestV[i] != -1)//不在选中点集中            {                int cost = g[newV][i];                if(cost < lowCost[i])                {                //更新邻接信息,O(N^3)到O(N^2)的关键                    lowCost[i] = cost;                    closestV[i] = newV;                }                if(lowCost[i] < minCost)                    minCost = lowCost[VtoAdd=i];            }        ans += minCost;        closestV[newV=VtoAdd] = -1;        selectVNum++;    }    return ans;}void initG(){    for( int i = 0 ; i < n ; i++ )        for( int j = 0 ; j < n ; j++ )            g[i][j] = INF;}int main(){    while( scanf("%d", &n) , n )    {        for( int i = 0 ; i < n ; i++ )            scanf("%s", t[i]);        //initG();        for( int i = 0 ; i < n ; i++ )            for( int j = i+1 ; j < n ; j++ )            {                int d = 0;                //获得边权值                for( int k = 0 ; k < 7 ; k++ )                    if( t[i][k] != t[j][k] )                        d++;                //向邻接矩阵赋边权值,看得出来是稠密图,相当稠密                g[i][j] = d;                g[j][i] = d;            }        printf("The highest possible quality is 1/%d.\n", Prim());    }    return 0;}
Kruskal:
//Memory: 25256KTime: 1250MS#include<cstdio>#include<cstring>#include<vector>#include<algorithm>using namespace std;const int N = 2000;struct edge{    edge( int A , int B , int V ):a(A),b(B),v(V){}    int a , b , v;    bool operator < ( const edge &e )const    {        return v < e.v;    }};vector<edge> l;int father[N+1] , ans , eN;char t[N][8];int getFather(int x){    return (!father[x])?x:(father[x] = getFather(father[x]));}void Union( int x , int y , int v ){    int fx = getFather(x);    int fy = getFather(y);    if( fx == fy )        return;    father[fy] = fx;    ans += v;    eN++;}void Kruskal(int n){    ans = eN = 0;    memset(father,0,sizeof(father));    vector<edge>::iterator it;    for( it = l.begin() ; it != l.end() ; it++ )    {        if( eN == n-1 )            return;        Union( it->a , it->b , it->v );    }}int main(){    int n;    while( scanf("%d", &n) , n )    {        for( int i = 0 ; i < n ; i++ )            scanf("%s", t[i]);        vector<edge>().swap(l);        for( int i = 0 ; i < n ; i++ )            for( int j = i+1 ; j < n ; j++ )            {                int d = 0;                for( int k = 0 ; k < 7 ; k++ )                    if( t[i][k] != t[j][k] )                        d++;                l.push_back(edge(i+1,j+1,d));            }        sort(l.begin(),l.end());        Kruskal(n);        printf("The highest possible quality is 1/%d.\n", ans);    }    return 0;}
虽然Kruskal我用了vector,空间效率比较起来有水分,但是时间效率的差别还是一目了然的吧。

0 0
原创粉丝点击