【题解】gym102361E Escape(分层图)
https://vjudge.net/problem/Gym-102361E
容易证明不会存在共用转换器的合法方案,因为出口互不相同且一旦共用转换器,要么以后走一样的路(这样就到最后两个机器人到了一个出口),要么有一个机器人的路径是非法的(同理)。
由此可以推断一段路径最多只会被一个机器人覆盖(路径相交不算)
这道题最主要是观察到这个性质。然后就可以做了。
建立两张网格图G1和G2,一张图只有上下的边,另一张图只有左右的边。两张图的对应格子连一条双向边。出入口在G1上处理一下即可。
//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std; typedef long long ll;
inline int qr(){
int ret=0,f=0,c=getchar();
while(!isdigit(c)) f|=c==45,c=getchar();
while( isdigit(c)) ret=ret*10+c-48,c=getchar();
return f?-ret:ret;
}
const int maxn=2e4+5;
int head[maxn],cur[maxn],d[maxn],cnt,S,T,id[105][105],n,m,a,b,pa[105],pb[105];
char c[105][105];
struct E{int to,nx,w;}e[maxn<<4];
void add(int fr,int to,int w,int init=0){
static int cnt=1;
if(init) return cnt=1,void();
e[++cnt]=(E){to,head[fr],w}; head[fr]=cnt;
e[++cnt]=(E){fr,head[to],0}; head[to]=cnt;
}
bool bfs(){
memset(d,0,sizeof d);
memcpy(cur,head,sizeof cur);
static queue<int> q;
d[S]=1; q.push(S);
while(q.size()){
int now=q.front();
q.pop();
for(int t=head[now];t;t=e[t].nx)
if(e[t].w>0&&!d[e[t].to])
q.push(e[t].to),d[e[t].to]=d[now]+1;
}
return d[T];
}
int dfs(int now,int fl){
if(now==T||fl==0) return fl;
int ret=0,p;
for(int&t=cur[now];t;t=e[t].nx)
if(d[e[t].to]==d[now]+1)
p=dfs(e[t].to,min(e[t].w,fl)),fl-=p,ret+=p,e[t].w-=p,e[t^1].w+=p;
return ret;
}
int Dinic(){
int ret=0;
while(bfs()) ret+=dfs(S,1e9);
return ret;
}
int calch(int i,int j){return 3+((i-1)*m+j-1)*2;}
int calcv(int i,int j){return 4+((i-1)*m+j-1)*2;}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
int TT=qr();
while(TT--){
n=qr(); m=qr(); a=qr(); b=qr();
memset(head,0,sizeof head); add(1,1,1,1);
for(int t=1;t<=n;++t) scanf("%s",c[t]+1);
S=1; T=2;
for(int t=1;t<=a;++t) pa[t]=qr();
for(int t=1;t<=b;++t) pb[t]=qr();
for(int t=1;t<=n-1;t++)
for(int i=1;i<=m;i++)
if(c[t][i]=='0' && c[t+1][i]=='0')
add(calcv(t,i),calcv(t+1,i),1),
add(calcv(t+1,i),calcv(t,i),1);
for(int t=1;t<=n;t++)
for(int i=1;i<=m-1;i++)
if(c[t][i]=='0'&&c[t][i+1]=='0')
add(calch(t,i),calch(t,i+1),1),
add(calch(t,i+1),calch(t,i),1);
for(int t=1;t<=n;t++)
for(int i=1;i<=m;i++)
if(c[t][i]=='0')
add(calch(t,i),calcv(t,i),1),
add(calcv(t,i),calch(t,i),1);
for(int t=1;t<=a;t++) if(c[1][pa[t]]=='0') add(1,calcv(1,pa[t]),1);
for(int t=1;t<=b;t++) if(c[n][pb[t]]=='0') add(calcv(n,pb[t]),2,1);
int sav=Dinic();
if(sav==a) puts("Yes");
else puts("No");
}
return 0;
}