花了好长时间去理解题意,看来英语阅读能力还有待提高。

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

例如有如下4个编号:

aaaaaaa
baaaaaa
abaaaaa
aabaaaa

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

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

以下是TLE版本:

}

继续探索Prime中。。。

参考链接:http://www.5ushare.com/bbs/redirect.php?fid=5&tid=46&goto=nextoldset




隔了好长时间,又回来做最小生成树了,这次把这题很轻松的AC了,用了PRIM算法配合手工优先权队列。

啊,发现当时自己好小白啊。

下面是AC代码:


/*=========================================
Prob  :poj1789 Truck History 
Type  :最小生成树
Status:AC
Time  :360MS
Memory:15636K
Author:myst
Remark:
==========================================
*/
#include 
<iostream>
#define SIZ 2010
#define INF INT_MAX
using namespace std;
int N;
int map[SIZ][SIZ];
bool visited[SIZ];
int dis[SIZ];
//-------------priority queue----------------------
int heap_size;
int heap[SIZ];
int SWAP(int i, int j)
{
    heap[i]
^=heap[j];heap[j]^=heap[i];heap[i]^=heap[j];
    
return 0;
}
int MIN_HEAPIFY(int i)
{
    
int l=i<<1;
    
int r=(i<<1)+1;
    
int min;
    
if (l<=heap_size && dis[heap[l]]<dis[heap[i]]) min=l;
        
else min=i;
    
if (r<=heap_size && dis[heap[r]]<dis[heap[min]]) min=r;
    
if (min!=i){
        SWAP(min, i);
        MIN_HEAPIFY(min);
    }
    
return 0;
}
int BUILD_HEAP()
{
    
for (int i=heap_size>>1;i>=1;i--)
        MIN_HEAPIFY(i);
    
return 0;
}
int EXTRACT_MIN()
{
    
int min=heap[1];
    SWAP(
1, heap_size);
    heap_size
--;
    
return min;
}
//-------------------------------------------------
int MST_PRIM()
{
    
int ans=0;
    
for (int i=1;i<=N;i++){
        dis[i]
=INF;
        visited[i]
=0;
        heap[i]
=i;
    }
    dis[
1]=0;
    heap_size
=N;
    BUILD_HEAP();
    
while (heap_size>0){
        
int u=EXTRACT_MIN();//为减少操作,EXTRACT_MIN没有执行MIN_HEAPIFY,统一到下面BUILD_HEAP()一起执行。
        visited[u]=1;
        ans
+=dis[u];
        
for (int j=1;j<=N;j++){
            
if (!visited[j] && map[u][j] && map[u][j]<dis[j])
                dis[j]
=map[u][j];
        }
        BUILD_HEAP();
    }
    
return ans;
}
int main()
{
    
//freopen("in.txt", "r", stdin);
    char code[SIZ][10];
    
while (scanf("%d"&N) && N){
        
for (int i=1;i<=N;i++)
            scanf(
"%s", code[i]);

        
for (int i=1;i<=N-1;i++){
            
for (int j=i+1;j<=N;j++){
                
int dif=0;
                
for (int k=0;k<7;k++)
                    
if (code[i][k]!=code[j][k]) dif++;
                map[i][j]
=dif;
                map[j][i]
=dif;
            }
        }
        printf(
"The highest possible quality is 1/%d.\n", MST_PRIM());
    }
    
return 0;
}
END

相关文章: