【codeforces 516B】Drazil and Tiles

时间:2024-01-01 23:59:39

题目链接:

  http://codeforces.com/problemset/problem/516/B

题解:

  首先可以得到一个以‘.’为点的无向图,当存在一个点没有边时,无解。然后如果这个图边双联通无唯一解。

  同时观察可知,只有一条边的点只有唯一一种连法,所以我们可以直接将其与其相连点从图中删除,再考虑剩下图中是否还有只有一条边的点,直到所有的结点都被删除,或剩下双联通分量以及存在没有边的结点为止。

  正确性……显然吧。时间复杂度$O(n^{2})$。

代码:

  

 #include<cstdio>
inline int read(){
int s=,k=;char ch=getchar();
while(ch<''||ch>'') k=ch=='-'?-:k,ch=getchar();
while(ch>&&ch<='') s=s*+(ch^),ch=getchar();
return s*k;
}
const int N=;
int n,m;
char map[N][N];
char result[N][N];
struct node {
int x,y;
};
node q[N*N];
int l,r;
int xx[]={,-,,},yy[]={,,,-};
char z[]={'^','v','<','>','v','^','>','<'};
int pan(int x,int y){
int ans=;
for(int i=;i<;i++){
int nx=x+xx[i],ny=y+yy[i];
if(map[nx][ny]=='.') ans++;
}
return ans;
}
inline bool solve(){
int sum=;
for(int i =;i<=n;i++)
for(int j=;j<=m;j++){
if(map[i][j]=='*'){
result[i][j]=map[i][j];
continue;
}
sum++;
int t=pan(i,j);
if(t==) return ;
else if(t==) q[r++]=(node){i,j};
}
if(sum&) return false;
int t=;
while(l<r){
node now=q[l++];
int x=now.x,y=now.y;
if(map[x][y]!='.') continue;
for(int i=;i<;i++){
int nx=x+xx[i],ny=y+yy[i];
if(map[nx][ny]=='.'){
t++;
map[x][y]=;
map[nx][ny]=;
result[x][y]=z[i];
result[nx][ny]=z[i+];
for(int j=;j<;j++){
int tx=nx+xx[j],ty=ny+yy[j];
if(map[tx][ty]=='.'){
int t=pan(tx,ty);
if(t==) q[r++]=(node){tx,ty};
if(t==) return false;
}
}
break;
}
if(i==) return false;
}
}
return t>=sum/;
}
int main(){
n=read(),m=read();
for(int i=;i<=n;result[i][m+]='\n',i++)
scanf("%s",map[i]+);
bool ans=solve();
// printf("\n");
if(ans){
for(int i=;i<=n;i++)
for(int j=;j<=m+;j++){
printf("%c",result[i][j]);
}
}
else printf("Not unique\n");
}