// 1856K 797MS G++
#include <stdio.h>
#include <string.h>
#define MAX 35
#define GRID_MAX MAX*MAX
int G[MAX][MAX];
char G_relation[GRID_MAX][GRID_MAX];
int M; // length
int N; // height
int K;
int validGridNum;
int V1[GRID_MAX];
int V2[GRID_MAX];
char waittingMove[GRID_MAX];
char getPair(int curId) {
for (int i = 1; i <= validGridNum; i++) {
if (G_relation[curId][i]) { // if curId connect i
if (!V2[i]) { // if i not assigned yet
V1[curId] = i;
V2[i] = curId;
return 1;
} else {
if (!waittingMove[V2[i]]) { // if i's owner do not waitting move
waittingMove[V2[i]] = 1; // try to move, waiting
if (getPair(V2[i])) {
V1[curId] = i;
V2[i] = curId;
return 1;
}
}
}
}
}
return 0;
}
void solve() {
validGridNum = N*M - K;
int gridId = 1;
for (int j = 0; j < N; j++) { // y
for (int i = 0; i < M; i++) { // x
if (G[i][j] != -1) {
G[i][j] = gridId++;
// printf("%d %d %d\n", i, j, G[i][j]);
}
}
}
// for (int j = 0; j < N; j++) {
// for (int i = 0; i< M; i++) {
// printf("%d ", G[i][j]);
// }
// printf("\n");
// }
for (int i = 0; i < M; i++) { //x
for (int j = 0; j < N; j++) { //y
int curId = G[i][j];
if (curId == -1) { // hole
continue;
}
//up
if (j < N-1) {
int upGridId = G[i][j+1];
if (upGridId != -1) { // upNode is not a hole
G_relation[curId][upGridId] = 1;
// printf("up %d %d\n", i, j);
}
}
//down
if (j > 0) {
int downGridId = G[i][j-1];
if (downGridId != -1) {
G_relation[curId][downGridId] = 1;
// printf("down %d %d\n", i, j);
}
}
//left
if (i > 0) {
int leftGridId = G[i-1][j];
if (leftGridId != -1) {
G_relation[curId][leftGridId] = 1;
// printf("left %d %d %d\n", i, j, G[i-1][j]);
}
}
//right
if (i < M-1) {
int rightGridId = G[i+1][j];
if (rightGridId != -1) {
G_relation[curId][rightGridId] = 1;
// printf("right %d %d %d\n", i, j, G[i+1][j]);
}
}
}
}
// for (int i = 1; i <= validGridNum; i++) {
// for (int j = 1; j <= validGridNum; j++) {
// printf("%d ", G_relation[i][j]);
// }
// printf("\n");
// }
int maxMatch = 0;
for (int i = 1; i <= validGridNum; i++) {
memset(waittingMove, 0, sizeof(waittingMove));
if (getPair(i)) {
maxMatch++;
}
}
// for (int i = 1; i <= validGridNum; i++) {
// printf("%d %d\n", i, V1[i]);
// }
// printf("%d %d\n", maxMatch, validGridNum);
if (maxMatch == validGridNum) {
printf("YES\n");
} else {
printf("NO\n");
}
}
int main() {
while(scanf("%d %d %d", &N, &M, &K) != EOF) {
memset(G, 0, sizeof(G));
memset(V1, 0, sizeof(V1));
memset(V2, 0, sizeof(V2));
memset(G_relation, 0, sizeof(G_relation));
validGridNum = 0;
for (int i = 0; i < K; i++) {
int x;
int y;
scanf("%d %d", &x, &y);
G[x-1][y-1] = -1; // a hole is -1
}
solve();
}
}
用的是点复制法来建的二分图,
每个点代表board上的一个不是hole的grid,依次从左到右,从下到上的编号,
然后,每个grid和其上下左右相邻的非hole的grid之间有连接的边,
在最后判断是否能够成功时有点迷糊, 直觉上直接用最大匹配数是否等于grid个数做的判断。
但是还不能清楚的解释原因,而觉得更严谨的应该是在这些最大匹配的边里面挨个检查边的端点,看是否有 grid数量/2的边(其实就是木板)的端点 将grid全部覆盖(这样就代表这题意 ,用木板在没有重叠的情况下将grid全部覆盖).