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(  ) {
    
forint 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 ) {
    
forint 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;
    
forint 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 ) {
    
forint 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;
        }
    }
    }
    
forint 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此增广路操作
    forint 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 ) );
    
forint i=0;i<n;i++ )
        a[ i ]
=st( A[ i ],B[ i ],C[ i ] );
    
    
//构造二分图
    forint i=0;i<n;i++ ) {
        
forint j=0;j<n;j++ ) {
        
if( can_eat( a[ i ],a[ j ] ) ) {
            gr[ 
2*i ][ j ]=1;
            gr[ 
2*i+1 ][ j ]=1;
        }
        }
        
forint 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(  );
    }
};


posted on 2007-07-20 21:34  woodfish  阅读(282)  评论(0编辑  收藏  举报

导航