题解 CF1567F【One-Four Overload】
这里首先把与某个被标记的格子相邻的未被标记的格子数量记作这个格子的度数。我们分别考虑度数为
- 对于度数为
0 的格子,必定填0 。 - 对于度数为
1 或3 的格子,很明显只要这样的格子存在,就必然无解。 - 对于度数为
2 的格子,与它相邻的两个未被标记的格子一个是1 ,另外一个是4 。 - 对于度数为
4 的格子,与它相邻的四个未被标记的格子两个是1 ,另外两个是4 。
如果没有度数为
这里我们可以发现,这样连出来的图一定是二分图。尝试反证,假设我们连出来了一个奇环,首先环上会出现两类边,第一类是直着连的,例如连接
环在网格上会围成一个简单多边形。对于每个第一类边,都会对应一个标记过的格子,并且这个格子在多边形内外各有一个相邻的标记过的格子。根据题目已知信息,每个被标记的格子度数都是偶数,因此每个连通块中,被标记的格子对应的点可以形成一个欧拉回路。这个欧拉回路一定是会进出这个多边形若干次,假定这个回路从多边形外出发,那么它最终一定会回到多边形外,反之亦然。但是如果第一类边只有奇数个,那么在多边形上的点也只有奇数个,这里我们暂时先假设这些点处于同一连通块。但是由于每个在多边形上的点只能经过一次,因此从多边形外出发,无法回到多边形外,欧拉回路不存在,与实际情况矛盾。所以没有奇环。
上面的证明假设了这些点处于同一连通块的情况,还需要考虑这些点处于不同连通块的情况,不过其实都是一样的,每个连通块会用掉偶数个点,本质还是奇偶性不满足。
接下来考虑把度数为
这样看起来不太可做,但实际上,加上度数为
连完之后,同样可以证明,最后的图还是一个二分图。因此这样连边虽然让限制更加严格了,但是仍然保证能求出一组解。
说到这里也差不多了,下面是代码:
写得比较丑。。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll ec = 0,to[1000005],nxt[1000005],hed[250005],col[250005];
ll n,m,flg;
char ch[505][505];
void add_edge(ll f,ll t){
++ ec; to[ec] = t; nxt[ec] = hed[f]; hed[f] = ec;
++ ec; to[ec] = f; nxt[ec] = hed[t]; hed[t] = ec;
}
void dfs(ll u){
for(ll v,i = hed[u];i;i = nxt[i]){
v = to[i];
if(col[v]) continue;
col[v] = 5 - col[u];
dfs(v);
}
}
ll get_id(ll x,ll y){
return (x - 1) * m + y;
}
int main(){
ios::sync_with_stdio(false);
flg = 1;
cin >> n >> m;
for(ll i = 1;i <= n;i ++){
for(ll j = 1;j <= m;j ++){
cin >> ch[i][j];
}
}
for(ll i = 2;i < n;i ++){
for(ll tmp,tu,tv,j = 2;j < m;j ++){
if(ch[i][j] != 'X') continue;
tmp = (ch[i - 1][j] == 'X') + (ch[i][j - 1] == 'X') + (ch[i + 1][j] == 'X') + (ch[i][j + 1] == 'X');
if(tmp == 1 || tmp == 3) flg = 0;
if(tmp == 0){
add_edge(get_id(i - 1,j),get_id(i,j - 1));
add_edge(get_id(i - 1,j),get_id(i,j + 1));
add_edge(get_id(i + 1,j),get_id(i,j - 1));
add_edge(get_id(i + 1,j),get_id(i,j + 1));
}
if(tmp == 2){
tu = tv = -1;
if(ch[i - 1][j] == '.'){
if(tu == -1) tu = get_id(i - 1,j);
else tv = get_id(i - 1,j);
}
if(ch[i][j - 1] == '.'){
if(tu == -1) tu = get_id(i,j - 1);
else tv = get_id(i,j - 1);
}
if(ch[i + 1][j] == '.'){
if(tu == -1) tu = get_id(i + 1,j);
else tv = get_id(i + 1,j);
}
if(ch[i][j + 1] == '.'){
if(tu == -1) tu = get_id(i,j + 1);
else tv = get_id(i,j + 1);
}
add_edge(tu,tv);
}
}
}
if(!flg){
cout << "NO\n";
return 0;
}
cout << "YES\n";
for(ll u,i = 1;i <= n;i ++){
for(ll j = 1;j <= m;j ++){
if(ch[i][j] == 'X') continue;
u = get_id(i,j);
if(!col[u]){
col[u] = 1;
dfs(u);
}
}
}
for(ll i = 1;i <= n;i ++){
for(ll tmp,j = 1;j <= m;j ++){
tmp = (ch[i - 1][j] == 'X') + (ch[i][j - 1] == 'X') + (ch[i + 1][j] == 'X') + (ch[i][j + 1] == 'X');
if(ch[i][j] == 'X') cout << ((4 - tmp) >> 1) * 5;
else cout << col[get_id(i,j)];
cout << (j == m ? '\n' : ' ');
}
}
return 0;
}