有一些鲨鱼要进行晚餐,他们要互相吃对方。每个对于都有一个尺寸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( );
}
};