题目大意:有个网格图,每个格子是
炮台:可以向上下’|‘或者左右’-‘发射激光(你来决定向上下还是左右)
镜子:两种’\‘或者’/’,成45°反射激光
障碍:’#’:激光遇到会消失。激光出边界也会消失。
空地:’.’
现在你要给每个炮台确定方向,使得不存在一个炮台能打到另一个炮台,并且每个空地至少被一个炮台的激光经过(激光可以相交)。
T
≤
100
,
n
,
m
≤
50
T\le100,n,m\le50
T≤100,n,m≤50
题解:
不难发现如果不存在一个炮台击中另一个炮台,那么每个空地的水平方向不可能有两束来自不同炮台的激光,竖直同理。
因此先处理每个炮台不会轰到另一个炮台的可行方向,判定是否存在一个空地无法被到达,是否一个空地只被一个炮台的一个方向经过,还有就是一个空地是否两个方向会被不同的炮台经过(注意被同一个炮台的两个方向击中是另外一种情况,这时候这个空地需要被忽略),最后一种情况就是一个2SAT。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define Rep(i,v) rep(i,0,(int)v.size()-1)
#define lint long long
#define ull unsigned lint
#define db long double
#define pb push_back
#define mp make_pair
#define fir first
#define sec second
#define gc getchar()
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
typedef pair<int,int> pii;
typedef set<int>::iterator sit;
inline int inn()
{
int x,ch;while((ch=gc)<'0'||ch>'9');
x=ch^'0';while((ch=gc)>='0'&&ch<='9')
x=(x<<1)+(x<<3)+(ch^'0');return x;
}
//P : choose LR; Q : choose UD
const int LEN=60,N=LEN*LEN*2,M=1000000;
int P[LEN][LEN],Q[LEN][LEN],vis[LEN][LEN];
pii las[LEN][LEN],mst[LEN][LEN];
char bd[LEN][LEN];stack<int> s;
struct edges{
int to,pre;
}e[M];int h[N],etop,dfn[N],low[N],dfc,cc,sta[N],no_ans,bel[N],cant[N];
inline int add_edge(int u,int v) { return /*debug(u)sp,debug(v)ln,*/e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
int tarjan(int x)
{
s.push(x),dfn[x]=low[x]=++dfc,sta[x]=1;
for(int i=h[x],y;i;i=e[i].pre)
if(!sta[y=e[i].to]) tarjan(y),low[x]=min(low[x],low[y]);
else if(sta[y]==1) low[x]=min(low[x],dfn[y]);
if(low[x]==dfn[x])
{
bel[x]=++cc,sta[x]=2;
for(int y=s.top();y!=x;s.pop(),y=s.top())
bel[y]=cc,sta[y]=2;s.pop();
}
return 0;
}
inline int trd(int &dx,int &dy,char c)
{
if(c=='\\') swap(dx,dy);
else{// '/'
if(dx) dy=-dx,dx=0;
else dx=-dy,dy=0;
}
return 0;
}
#define OK(i,j,n,m) ((i)>=1&&(i)<=(n)&&(j)>=1&&(j)<=(m)&&bd[i][j]!='#')
#define DO(i,j,p,q)\
if(bd[i][j]=='/'||bd[i][j]=='\\') trd(dx,dy,bd[i][j]);\
else if(bd[i][j]=='.'){\
if(!vis[i][j]) mst[i][j]=mp(q,p);\
else if(mst[i][j]!=mp(q,p)) mst[i][j]=mp(0,0);\
if(!vis[i][j]) las[i][j]=mp(q,p);\
else if(las[i][j]!=mp(q,p)&&las[i][j]!=mp(p,q)) add_edge(p,las[i][j].fir),add_edge(las[i][j].sec,q);\
vis[i][j]=1;\
}
#define GO(p,q,_dx,_dy) for(int dx=_dx,dy=_dy,i=x+dx,j=y+dy;OK(i,j,n,m);i+=dx,j+=dy) DO(i,j,p,q)
#define GOCANT(p,_dx,_dy) for(int dx=_dx,dy=_dy,i=x+dx,j=y+dy;OK(i,j,n,m);i+=dx,j+=dy)\
if(bd[i][j]=='|'||bd[i][j]=='-') { cant[p]=1;break; }\
else if(bd[i][j]=='/'||bd[i][j]=='\\') trd(dx,dy,bd[i][j]);
inline int getcant(int x,int y,int n,int m)
{
int p=P[x][y],q=Q[x][y];
GOCANT(p,0,1)GOCANT(p,0,-1)
GOCANT(q,1,0)GOCANT(q,-1,0)
if(cant[p]&&cant[q]) return no_ans=1;
return 0;
}
inline int go(int x,int y,int n,int m)
{
// cerr ln,debug(x)sp,debug(y)ln;
int p=P[x][y],q=Q[x][y];cant[p]=cant[q]=0;
getcant(x,y,n,m);if(no_ans) return 0;
if(!cant[q]) { GO(p,q,1,0)GO(p,q,-1,0) }
if(!cant[p]) { GO(q,p,0,1)GO(q,p,0,-1) }
//debug(cant[p])sp,debug(cant[q])ln;
return 0;
}
int main()
{
for(int T=inn();T;T--)
{
// static int curT=0;cout<<++curT<<" ";
int n=inn(),m=inn(),c=0;
no_ans=0,etop=0;
rep(i,1,n) scanf("%s",bd[i]+1);
rep(i,1,n) rep(j,1,m) las[i][j]=mp(0,0),vis[i][j]=0;
rep(i,1,n) rep(j,1,m)
{
if(bd[i][j]=='|'||bd[i][j]=='-')
P[i][j]=++c,Q[i][j]=++c,h[c-1]=h[c]=0,go(i,j,n,m);
else P[i][j]=0;
if(no_ans) { printf("IMPOSSIBLE\n");goto END_LOOP; }
}
// cerr ln;
rep(i,1,n) rep(j,1,m) if(P[i][j])
{
if(cant[P[i][j]]) add_edge(P[i][j],Q[i][j]);//,debug(P[i][j])sp,debug(Q[i][j])ln;
if(cant[Q[i][j]]) add_edge(Q[i][j],P[i][j]);//,debug(Q[i][j])sp,debug(P[i][j])ln;
}
rep(i,1,n) rep(j,1,m) if(bd[i][j]=='.'&&!vis[i][j])
{ printf("IMPOSSIBLE\n");goto END_LOOP; }
rep(i,1,n) rep(j,1,m) if(bd[i][j]=='.'&&mst[i][j].sec)
add_edge(mst[i][j].sec,mst[i][j].fir);
memset(sta,0,sizeof(int)*(c+1)),dfc=0,cc=0;
rep(i,1,c) if(!sta[i]) tarjan(i);
for(int i=1,x,y;i<=n;i++) rep(j,1,m) if(P[i][j])
{
if((x=bel[P[i][j]])==(y=bel[Q[i][j]])) { printf("IMPOSSIBLE\n");goto END_LOOP; }
else if(x<y) bd[i][j]='-';else bd[i][j]='|';
}
printf("POSSIBLE\n");
rep(i,1,n) { rep(j,1,m) printf("%c",bd[i][j]);printf("\n"); }
END_LOOP:continue;
}
return 0;
}