• 【题解】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;
    }
    
    
    
  • 相关阅读:
    du熊学斐波那契I
    《博客园精华集》分类索引
    C++中指针和引用的区别
    堆和栈的区别
    getch和getchar的区别
    class和struct
    ARM开发步骤
    ARM寻址方式
    存储器映射
    思维中的错误
  • 原文地址:https://www.cnblogs.com/winlere/p/12272396.html
Copyright © 2020-2023  润新知