输入样例1
3 3 4
1 2
1 3
2 1
2 2
3 3 4
1 2
1 3
2 1
3 2
输出样例1
Board 1 have 0 important blanks for 2 chessmen.
Board 2 have 3 important blanks for 3 chessmen.
二分图最大匹配问题,车在象棋里只能走直线,不能拐弯,所以为了不让车之间相互吃,得保证车不在同一行、同一列。行看作一个集合,列看作一个集合,最大匹配数就是能放的最大车的数量。
根据题目要求的重要点定义,如果该点不让放置车,则导致整个最大匹配数减少则说明该点为重要点。
值得注意的是我在写这个题的时候尝试用memset函数将vis数组初始化为1,却导致他们都等于一个较大的数,让我明白了memset只能将数组初始化为-1或0,其他的数字都会导致不可预料的后果。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int n, m, k;
int imap[ 105 ] [ 105 ] ;
int vis[ 105 ] , link[ 105 ] ;
bool dfs ( int x) {
for ( int i= 1 ; i<= m; i++ ) {
if ( vis[ i] == 0 && imap[ x] [ i] == 1 ) {
vis[ i] = 1 ;
if ( link[ i] == - 1 || dfs ( link[ i] ) == true ) {
link[ i] = x;
return true ;
}
}
}
return false ;
}
int main ( )
{
int a, b, cc;
cc= 0 ;
while ( ~ scanf ( "%d%d%d" , & n, & m, & k) ) {
memset ( imap, 0 , sizeof ( imap) ) ;
while ( k-- ) {
scanf ( "%d%d" , & a, & b) ;
imap[ a] [ b] = 1 ;
}
memset ( link, - 1 , sizeof ( link) ) ;
int sum= 0 ;
for ( int i= 1 ; i<= n; i++ ) {
memset ( vis, 0 , sizeof ( vis) ) ;
if ( dfs ( i) == true ) sum++ ;
}
int important= 0 ;
int ind= 0 ;
for ( int i= 1 ; i<= n; i++ ) {
for ( int j= 1 ; j<= m; j++ ) {
if ( imap[ i] [ j] == 1 ) {
ind= 0 ;
imap[ i] [ j] = 0 ;
memset ( link, - 1 , sizeof ( link) ) ;
for ( int z= 1 ; z<= n; z++ ) {
memset ( vis, 0 , sizeof ( vis) ) ;
if ( dfs ( z) == true ) ind++ ;
}
if ( ind< sum) important++ ;
imap[ i] [ j] = 1 ;
}
}
}
printf ( "Board %d have %d important blanks for %d chessmen.\n" , ++ cc, important, sum) ;
}
return 0 ;
}