CodeForces - 1567F F. One-Four Overload
题目:
给你个网格, X
为染色的,.
为没染色的,对于没染色的位置只能是
1
1
1或
4
4
4,染色的位置为上下左右未染色的位置上值和,并且要求染色的部分的值为5的倍数。要求构造一组解
例:
input:
5 5
…
.XXX.
.X.X.
.XXX.
…
output:
YES
4 1 4 4 1
4 5 5 5 1
4 5 1 5 4
1 5 5 5 4
1 4 4 1 4
思路:
对于染色的位置,他只能和
0
0
0个,
2
2
2个或者
4
4
4个未染色相邻。
当两个的时候要 : 一个为
1
1
1,一个为
4
4
4 既:两点不同.
当四个的时候要 :上下相同,左右相同。(为了不影响对角线方向的染色的部分)
2
−
s
a
t
2-sat
2−sat建边:
我对于四个的时候是要求上和左不同,下和右不同建的边。
代码
#include<iostream>
#include<cstring>
#include<map>
using namespace std;
const int N = 1e6+10;
int h[N],ne[N],e[N],idx;
void add(int a,int b){
ne[idx] = h[a] , e[idx] = b,h[a] = idx++;
}
map<pair<int,int>,int> gd;
int n,m,id;
char mp[510][510],ans[510][510];
bool st[N];
int stk[N],top;
int low[N],dfn[N],tim;
int scc[N],cnt;
void tarjan(int u){
st[u] = true;
stk[++top] = u;
dfn[u] = low[u] = ++ tim;
for(int i = h[u];~i;i=ne[i]){
int y = e[i];
if(!dfn[y]){
tarjan(y);
low[u] = min(low[u],low[y]);
}else if(st[y])low[u] = min(low[u],dfn[y]);
}
if(low[u] == dfn[u]){
int y ;
cnt++;
do{
y = stk[top--];
st[y] = false;
scc[y] = cnt;
}while(y != u);
}
}
int main(){
cin >> n >> m;
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++)
{
cin >> mp[i][j];
if(mp[i][j] == '.')gd[{i,j}] = ++id;
}
}
//add edge;
memset(h,-1,sizeof h);
pair<int,int> pii[5];
for(int i = 1;i<=n;i++){
for(int j = 1;j<=m;j++){
if(mp[i][j] == '.')continue;
int len = 0;
//**************************
//*注意这里的顺序,影响建边。*
//**************************
if(i - 1 >= 1 && mp[i-1][j] == '.')pii[++len] = {i-1,j};
if(j - 1 >= 1 && mp[i][j-1] == '.')pii[++len] = {i,j-1};
if(i + 1 <= n && mp[i+1][j] == '.')pii[++len] = {i+1,j};
if(j + 1 <= m && mp[i][j+1] == '.')pii[++len] = {i,j+1};
if(len&1){
cout << "NO" << endl;
return 0;
}
add(gd[pii[1]] + id , gd[pii[2]]);
add(gd[pii[2]] , gd[pii[1]] + id);
add(gd[pii[2]] + id , gd[pii[1]]);
add(gd[pii[1]] , gd[pii[2]] + id);
if(len == 4){
add(gd[pii[3]] + id , gd[pii[4]]);
add(gd[pii[4]] , gd[pii[3]] + id);
add(gd[pii[4]] + id , gd[pii[3]]);
add(gd[pii[3]] , gd[pii[4]] + id);
}
}
}
for(int i = 1;i<=id;i++)if(!dfn[i])tarjan(i);
for(int i = 1;i<=id;i++){
if(scc[i] == scc[i+id]){
cout << "NO" << endl;
return 0;
}
}
for(auto s : gd){
int x = s.first.first , y = s.first.second , p = s.second;
// cout << "x" << x << "y" << y << mp[x][y] << endl;
if(scc[p] < scc[p+id])ans[x][y] = '1';
else ans[x][y] = '4';
}
cout <<"YES" << endl;
for(int i = 1;i<=n;i++)
{
for(int j = 1;j<=m;j++){
if(mp[i][j] == '.' && !ans[i][j])printf("1 ");
else if(mp[i][j] == 'X'){
int res = 0;
if(i - 1 >= 1 && mp[i-1][j] == '.')res += ans[i-1][j] - '0';
if(i + 1 <= n && mp[i+1][j] == '.')res += ans[i+1][j] - '0';
if(j - 1 >= 1 && mp[i][j-1] == '.')res += ans[i][j-1] - '0';
if(j + 1 <= m && mp[i][j+1] == '.')res += ans[i][j+1] - '0';
printf("%d ",res);
}
else printf("%c ",ans[i][j]);
}
puts("");
}
return 0;
}
再水几天就退役了,over。