序
无序
正文
我们对此题观察,但是没什么好的方法
其实一开始会有几个想法:
- 搜索骗分
- 肯定是关于图的算法:
- 拓扑(跟度有关?
- 流算法
- 结论题??
- 打表??
我先想的搜索,就是说,这个东西能搜成环就搜,但是,不太行,好像不好搜呀。。
然后想拓扑,因为,每个点的度都是二,然后,,没有什么想法。。我们再想想 flow ,好像 ok
怎么建图,我们通过一个题目的描述,可以知道,每条边,都有2的流量代表进出一次,然后黑白染色,就行了
/* make by ltao */
const int Maxn=33;
#define Max Maxn*Maxn
int tt,n,m,h[Max],cnt,s,t,tot,gap[Max],dep[Max],maxflow;
bool flag[Max];
char ch;
struct Edge{
int to,lac,flow;
void insert(int x,int y,int z){to=y;lac=h[x];h[x]=cnt++;flow=z;}
}edge[Max*5];
void add_edge(int x,int y,int z){
edge[cnt].insert(x,y,z);
edge[cnt].insert(y,x,0);
}
void bfs(int s,int t){
memset(dep,-1,sizeof dep);
gap[0]=1;dep[t]=0;
queue<int> q;q.push(t);
while(!q.empty()){
int fr=q.front();q.pop();
for(int i=h[fr];i!=-1;i=edge[i].lac){
int to=edge[i].to;
if(dep[to]!=-1) continue;
dep[to]=dep[fr]+1;
gap[dep[to]]++;
q.push(to);
}
}
return ;
}
int dfs(int u,int min1){
if(u==t) return min1;
int sum=min1;
for(int i=h[u];i!=-1;i=edge[i].lac){
int to=edge[i].to;
if(!edge[i].flow||dep[to]+1!=dep[u]) continue;
int ret=dfs(to,min(sum,edge[i].flow));
sum-=ret;edge[i].flow-=ret;edge[i^1].flow+=ret;
if(!sum) return min1;
}
gap[dep[u]]--;
if(!gap[dep[u]]) dep[s]=tot;
gap[++dep[u]]++;
return min1-sum;
}
void ISAP(int s,int t){
bfs(s,t);
while(dep[s]<tot)
maxflow+=dfs(s,0x3f3f3f3f);
}
#define id(i,j) ((i-1)*m+j)
int main(){
// freopen("p2123.in","r",stdin);
// freopen("p2123.out","w",stdout);
tt=read();
while(tt--){
memset(flag,0,sizeof flag);
n=read();m=read();
s=0;t=n*m+1;
maxflow=0;tot=n*m;
for(int i=1;i<=n*m;++i){
ch=Get();
if(ch=='#') flag[i]=1,tot--;
}
// 定义
// the chesses which is its (i+j)%2 are black,else are white
// and s -> black,white->t
memset(h,-1,sizeof h);cnt=0;
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j){
int id=(i-1)*m+j;
if(flag[id]) continue;
if((i+j)%2){
add_edge(s,id,2);
if(i>1&&!flag[id(i-1,j)]) add_edge(id,id(i-1,j),1);
if(i<n&&!flag[id(i+1,j)]) add_edge(id,id(i+1,j),1);
if(j>1&&!flag[id(i,j-1)]) add_edge(id,id(i,j-1),1);
if(j<m&&!flag[id(i,j+1)]) add_edge(id,id(i,j+1),1);
}
else add_edge(id,t,2);
}
// 终于建好图了
ISAP(s,t);
if(maxflow<tot) printf("NO\n");
else printf("YES\n");
}
return 0;
}
以后都不准备加头文件了,咕
嵬
其实TJOI 每年都有网络流,抓住机会。