真是菜死了模板题都不会……
首先\(30 \times 30\)并不能插头DP,但是范围仍然很小所以考虑网络流。
注意每个点都要包含在一个回路中,那么每一个点的度数都必须为\(2\),也就是说每一个点必须向与它四连通的点中恰好\(2\)个连边。而“四连通”又是经典的黑白染色+二分图模型。
所以对于原图黑白染色,原点向黑点、白点向汇点连流量为\(2\)的边,相邻的黑点向白点连流量为\(1\)的边,跑一边Dinic看最大流等于需要打扫的格点数量。
#include<iostream>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<queue>
#define INF 0x3f3f3f3f
//This code is written by Itst
using namespace std;
inline int read(){
int a = 0;
char c = getchar();
bool f = 0;
while(!isdigit(c) && c != EOF){
if(c == '-')
f = 1;
c = getchar();
}
if(c == EOF)
exit(0);
while(isdigit(c)){
a = (a << 3) + (a << 1) + (c ^ '0');
c = getchar();
}
return f ? -a : a;
}
const int MAXN = 1e5 + 7 , MAXM = 1e6 + 7;
struct Edge{
int end , upEd , f , c;
}Ed[MAXM];
int head[MAXN];
int N , M , S , T , cntEd = 1;
queue < int > q;
inline void addEd(int a , int b , int c , int d = 0){
Ed[++cntEd].end = b;
Ed[cntEd].upEd = head[a];
Ed[cntEd].f = c;
Ed[cntEd].c = d;
head[a] = cntEd;
}
int cur[MAXN] , dep[MAXN];
inline bool bfs(){
while(!q.empty())
q.pop();
q.push(S);
memset(dep , 0 , sizeof(dep));
dep[S] = 1;
while(!q.empty()){
int t = q.front();
q.pop();
for(int i = head[t] ; i ; i = Ed[i].upEd)
if(Ed[i].f && !dep[Ed[i].end]){
dep[Ed[i].end] = dep[t] + 1;
if(Ed[i].end == T){
memcpy(cur , head , sizeof(head));
return 1;
}
q.push(Ed[i].end);
}
}
return 0;
}
inline int dfs(int x , int mF){
if(x == T)
return mF;
int sum = 0;
for(int &i = cur[x] ; i ; i = Ed[i].upEd)
if(Ed[i].f && dep[Ed[i].end] == dep[x] + 1){
int t = dfs(Ed[i].end , min(mF - sum , Ed[i].f));
if(t){
Ed[i].f -= t;
Ed[i ^ 1].f += t;
sum += t;
if(sum == mF)
break;
}
}
return sum;
}
int Dinic(){
int ans = 0;
while(bfs())
ans += dfs(S , INF);
return ans;
}
inline char getc(){
char c = getchar();
while(c == ' ' || c == '\n' || c == '\r')
c = getchar();
return c;
}
#define id(i,j) (((i) - 1) * M + j)
const int dir[4][2] = {0,1,0,-1,1,0,-1,0};
char mmap[32][32];
int main(){
#ifndef ONLINE_JUDGE
freopen("in" , "r" , stdin);
//freopen("out" , "w" , stdout);
#endif
for(int t = read() ; t ; --t){
N = read();
M = read();
T = N * M + 1;
memset(head , 0 , sizeof(head));
cntEd = 1;
int cnt = 0;
for(int i = 1 ; i <= N ; ++i)
for(int j = 1 ; j <= M ; ++j){
mmap[i][j] = getc();
if(mmap[i][j] == '.'){
++cnt;
if((i + j) & 1){
addEd(S , id(i , j) , 2);
addEd(id(i , j) , S , 0);
}
else{
addEd(id(i , j) , T , 2);
addEd(T , id(i , j) , 0);
}
}
}
for(int i = 1 ; i <= N ; ++i)
for(int j = 1 + (i & 1) ; j <= M ; j += 2){
if(mmap[i][j] == '.')
for(int k = 0 ; k < 4 ; ++k)
if(i + dir[k][0] && i + dir[k][0] <= N)
if(j + dir[k][1] && j + dir[k][1] <= M)
if(mmap[i + dir[k][0]][j + dir[k][1]] == '.'){
addEd(id(i , j) , id(i + dir[k][0] , j + dir[k][1]) , 1);
addEd(id(i + dir[k][0] , j + dir[k][1]) , id(i , j) , 0);
}
}
puts(!(cnt & 1) && Dinic() == cnt ? "YES" : "NO");
}
return 0;
}