HDU 1281 棋盘游戏 【二分图最大匹配】
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=1281
题意概括:
有N*M大的棋盘,要在里面放尽量多的“车”,求最多能放的车的个数,和为了放最多的车有多少个各自必须放车。
解题思路:
由“车”的规则可知,同一行或者同一列只能放一个车,可以放车的点作为边,对行和列最大匹配。然后遍历去点,如果去掉该点后最大匹配数减少,则说明那个点是不能去掉的点。
AC code:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <istream> 3 #include <cstring> 4 #include <algorithm> 5 #define INF 0x3f3f3f3f 6 #define LL long long 7 using namespace std; 8 9 const int MAXN = 111; 10 11 struct node 12 { 13 int x, y; 14 }cc[MAXN]; 15 int mmp[MAXN][MAXN]; 16 int linker[MAXN]; 17 bool used[MAXN]; 18 int N, M, K; 19 20 bool Find(int u) 21 { 22 for(int v = 1; v <= M; v++){ 23 if(mmp[u][v] && !used[v]){ 24 used[v] = true; 25 if(linker[v] == -1 || Find(linker[v])){ 26 linker[v] = u; 27 return true; 28 } 29 } 30 } 31 return false; 32 } 33 34 int Match() 35 { 36 int res = 0; 37 memset(linker, -1, sizeof(linker)); 38 for(int u = 1; u <= N; u++){ 39 memset(used, false, sizeof(used)); 40 if(Find(u)) res++; 41 } 42 return res; 43 } 44 45 int main() 46 { 47 int uu, vv, cnt = 0, T_case = 0; 48 while(~scanf("%d %d %d", &N, &M, &K)){ 49 memset(mmp, 0, sizeof(mmp)); 50 cnt = 0; 51 T_case++; 52 for(int i = 0; i < K; i++){ 53 scanf("%d%d", &uu, &vv); 54 mmp[uu][vv] = 1; 55 cc[i].x = uu; 56 cc[i].y = vv; 57 } 58 int ans = Match(); 59 // puts("zjy"); 60 int ans_node = 0; 61 for(int i = 0; i < K; i++){ 62 mmp[cc[i].x][cc[i].y] = 0; 63 if(ans > Match()) ans_node++; 64 mmp[cc[i].x][cc[i].y] = 1; 65 } 66 67 printf("Board %d have %d important blanks for %d chessmen.\n", T_case, ans_node, ans); 68 69 } 70 return 0; 71 }