poj1789 Truck History

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

题意大概是这样的:用一个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版本:

Code

继续探索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

你可能感兴趣的:(history)