3. 题目
3.1 CF 1475 F
题意
给一个0/1矩阵,求是否可以经过若干次整行或整列取反,变换成指定矩阵。
题解
先将初始矩阵和目标矩阵按位置异或,得到哪些位置需要变换,得到变换矩阵A。
如果
a
i
,
j
=
0
a_{i,j} = 0
ai,j=0, 那么第i行和第j列要么全变换,要么均不变换。
如果
a
i
,
j
=
0
a_{i,j} = 0
ai,j=0, 那么第i行和第j列只能有一个变换。
然后2-sat。
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N = 1010;
struct EDGE{
int to, nxt;
EDGE(){}
EDGE(int x, int y){ to = x, nxt = y;}
}edge[N * N * 4];
int t[N * 4], dfn[N * 4], low[N * 4], in[N * 4], a[N][N], st[N * 4], col[N * 4];
char s[N][N], ss[N];
int cnt, tot, colcnt, stop;
void myclear(int n)
{
for(int i = 1; i <= n * 4; i++)
t[i] = 0, dfn[i] = 0, low[i] = 0, st[i] = 0;
cnt = 0;
tot = 0;
stop = 0;
colcnt = 0;
}
void addedge(int x, int y)
{
edge[++tot] = EDGE(y, t[x]);
t[x] = tot;
}
void dfs(int x, int fa)
{
dfn[x] = ++cnt;
low[x] = cnt;
in[x] = 1;
st[++stop] = x;
for(int p = t[x]; p; p = edge[p].nxt)
{
int y = edge[p].to;
if(y == fa)
continue;
if(dfn[y] == 0)
{
dfs(y, x);
low[x] = min(low[y], low[x]);
}
else
if(in[y])
low[x] = min(low[x], dfn[y]);
}
in[x] = 0;
if(dfn[x] == low[x])
{
colcnt--;
int y = st[stop];
do{
y = st[stop];
col[y] = colcnt;
stop--;
}while(y != x);
}
}
int main()
{
int T;
scanf("%d", &T);
while(T)
{
T--;
int n;
scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%s", s[i] + 1);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
a[i][j] = s[i][j] - '0';
for(int i = 1; i <= n; i++)
scanf("%s", s[i] + 1);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
if(s[i][j] == '1')
a[i][j] ^= 1;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= n; j++)
{
if(a[i][j])
{
addedge(i, j + n + 2 * n);
addedge(j + n + 2 * n, i);
addedge(j + n, i + 2 * n);
addedge(i + 2 * n, j + n);
}
else
{
addedge(i, j + n);
addedge(j + n, i);
addedge(i + 2 * n, j + n + 2 * n);
addedge(j + n + 2 * n, i + 2 * n);
}
}
int flag = 1;
for(int i = 1; i <= n * 4; i++)
if(!dfn[i])
dfs(i, 0);
for(int i = 1; i <= n * 2; i++)
if(col[i] == col[i + 2 * n])
flag = 0;
if(flag)
printf("YES\n");
else
printf("NO\n");
myclear(n);
}
return 0;
}