Topcoder SRM 358:SharksDinner

有一些鲨鱼要进行晚餐,他们要互相吃对方。每个对于都有一个尺寸size,速度speed,和智力intelligence。鲨鱼A能够吃鲨鱼B当且进当A的size,speed,intelligence都大于或者等于B鲨鱼的。并且每个鲨鱼最多能够吃2个其它的鲨鱼。
现在给定int[] size, int[] speed and int[] intelligence,要求出最后存活的鲨鱼的最小数量。

分析:要求最后存活的鲨鱼的最小数量,就要 求被吃的鲨鱼的最大数量。
假设有n个鲨鱼,我们建立一个二分图,每个鲨鱼有3个顶点Ax1,Ax2,Bx,其中2个顶点Ax1,Ax2在二分图的左图中,另外一个顶点Bx在二分图的右图中,如果有鲨鱼x能够吃鲨鱼y,我们就建立边Ax1->By,Ax2->By,这样,问题就转化为求这个二分图的最大匹配match,最后的结果就是n-match.
二分图的最大匹配使用匈牙利算法(寻找增广路)

code:
#include  < iostream >
#include 
< vector >
using   namespace  std;

struct  st {
    
int  a[  3  ];
    st(  ) {
    
for int  i = 0 ;i < 3 ;i ++  ) a[ i ] = 0 ;
    }
    st( 
int  A, int  B, int  C ) {
    a[ 
0  ] = A;
    a[ 
1  ] = B;
    a[ 
2  ] = C;
    }
};

const   int  MAXN = 250 ;

bool  eq(  const  st &  x, const  st &  y ) {
    
for int  i = 0 ;i < 3 ;i ++  )
    
if ( x.a[ i ] != y.a[ i ] )
        
return   false ;
}

// 判断鲨鱼x是否能够吃鲨鱼y
bool  can_eat(  const  st &  x, const  st &  y ) {
    
if ( eq( x,y ) )  return   false ;
    
for int  i = 0 ;i < 3 ;i ++  )
    
if ( x.a[ i ] < y.a[ i ] )  return   false ;
    
return   true ;
}

st a[ MAXN ];                
// 保存鲨鱼信息
bool  gr[ MAXN ][ MAXN ];      // 二分图
int  n,m;                      // 二分图两个子图的节点数
int  match[ MAXN ];            // 记录二分图的匹配信息
bool  us[ MAXN ];              // 记录二分图第二个子图中的节点是否用过

// 从二分图的第一个子图中的v节点开始寻找增广路径
bool  go(  int  v ) {
    
for int  i = 0 ;i < m;i ++  ) {
    
if ( us[ i ] )  continue ;
    
if ( gr[ v ][ i ] ) {
        
if ( match[ i ] ==- 1  ) {
        us[ i ]
= 1 ;
        match[ i ]
= v;
        
return   true ;
        }
    }
    }
    
for int  i = 0 ;i < m;i ++  ) {
    
if ( us[ i ] )  continue ;
    
if ( gr[ v ][ i ] ) {
        us[ i ]
= 1 ;
        
if ( go( match[ i ] ) ) {
        match[ i ]
= v;
        
return   true ;
        }
    }
    }
    
return   false ;
}

// 进行最大二分匹配
int  matcher(  ) {
    
int  res = 0 ;
    memset( match,
255 , sizeof  match );
    
    
// 进行n此增广路操作
     for int  i = 0 ;i < n;i ++  ) {
    memset( us,
0 , sizeof  us );
    
if ( go( i ) )  ++ res;
    }
    
return  res;
}

class  SharksDinner {
public :
    
static   int  minSurvivors( vector < int >  A,vector < int >  B,vector < int >  C ) {
    n
= A.size(  );
    memset( gr,
0 , sizeof ( gr ) );
    
for int  i = 0 ;i < n;i ++  )
        a[ i ]
= st( A[ i ],B[ i ],C[ i ] );
    
    
// 构造二分图
     for int  i = 0 ;i < n;i ++  ) {
        
for int  j = 0 ;j < n;j ++  ) {
        
if ( can_eat( a[ i ],a[ j ] ) ) {
            gr[ 
2 * i ][ j ] = 1 ;
            gr[ 
2 * i + 1  ][ j ] = 1 ;
        }
        }
        
for int  j = 0 ;j < i;j ++  ) {
        
if ( eq( a[ i ],a[ j ] ) ) {
            gr[ 
2 * i ][ j ] = 1 ;
            gr[ 
2 * i + 1  ][ j ] = 1 ;
        }
        }
    }
    n
= 2 * A.size(  );
    m
= A.size(  );
    
return  m - matcher(  );
    }
};


你可能感兴趣的:(topcoder)