【题解】gym102361E Escape(分层图)

【题解】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;
}


posted @ 2020-02-07 11:33  谁是鸽王  阅读(294)  评论(0编辑  收藏  举报