专栏文章
题解:P1418 [TJOI2011] 构造矩阵
P1418题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @mio6mv2w
- 此快照首次捕获于
- 2025/12/02 14:13 3 个月前
- 此快照最后确认于
- 2025/12/02 14:13 3 个月前
先用最大流求出任意一个合格矩阵,再用如下 BFS 修改矩阵.
我们注意到如果想把一个位置的1修改成0,这个点的行和列都需要一个0修改成1,反之亦然,如此反复,如果形成了一个回路则可以修改最初的那个位置
形式化来讲就是:
如果能找到这样一条回路,那么就可以把路径上的点异或 后依然是一个合格矩阵.
我们以行和列为状态,行转移这一行上点等于0的列,列转移这一列上点等于1的行,这样转移路径上行列是交错的,然后递归修改交点即可.
修改一次复杂度为
要枚举每个点然后修改所以总复杂度为 基本上达不到理论复杂度,可以通过此题
提交记录
CPP我们注意到如果想把一个位置的1修改成0,这个点的行和列都需要一个0修改成1,反之亦然,如此反复,如果形成了一个回路则可以修改最初的那个位置
形式化来讲就是:
如果能找到这样一条回路,那么就可以把路径上的点异或 后依然是一个合格矩阵.
我们以行和列为状态,行转移这一行上点等于0的列,列转移这一列上点等于1的行,这样转移路径上行列是交错的,然后递归修改交点即可.
修改一次复杂度为
要枚举每个点然后修改所以总复杂度为 基本上达不到理论复杂度,可以通过此题
提交记录
#include <bits/stdc++.h>
using namespace std;
struct root {
int t;
int x;
} qq[1000001], accq[101][101];
int g[211][211], n, m, r, q[1000001], ac[1000001], ans[111][111], acc[101][101],acq[1000001];
void bfs(int x, int y) {
int l = 0, r = 0;
for (int i = 1; i <= max(n, m); i++) {
accq[1][i] = accq[2][i] = {0, 0};
acc[1][i] = acc[2][i] = 0;
}
qq[r++] = {1, x};
acc[1][x] = 1;
while (r > l) {
root now = qq[l++];
if (now.t == 2 && now.x == y) {
ans[x][y] ^= 1;
//递归输出交点
while (1) {
root qs = accq[now.t][now.x];
if (!qs.x) break;
if (now.t == 2)
ans[qs.x][now.x] ^= 1;
else
ans[now.x][qs.x] ^= 1;
now = qs;
}
break;
}
if (now.t == 1) {
//不能跑已经处理过的点
for (int i = now.x == x ? y : 1; i <= m; i++)
if (ans[now.x][i] == 0 && !acc[2][i]) {
qq[r++] = {2, i};
acc[2][i] = 1;
accq[2][i] = {now.t, now.x};
}
} else {
//不能跑已经处理过的点
for (int i = x; i <= n; i++)
if (ans[i][now.x] == 1 && !acc[1][i]) {
qq[r++] = {1, i};
acc[1][i] = 1;
accq[1][i] = {now.t, now.x};
}
}
}
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
cin >> r;
g[0][i] = r;
}
for (int j = 1; j <= m; j++) {
cin >> r;
g[j + n][n + m + 1] = r;
}
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++) g[i][j + n] = 1;
//最大流
while (1) {
int l = 0, r = 0;
q[r++] = 0;
ac[0] = 1;
for (int i = 1; i <= n + m + 1; i++) ac[i] = acq[i] = 0;
int f = 1;
while (r > l) {
int now = q[l++];
if (now == n + m + 1) {
while (now) {
g[acq[now]][now]--;
g[now][acq[now]]++;
now = acq[now];
}
f = 0;
break;
}
for (int i = 0; i <= n + m + 1; i++)
if (!ac[i] && g[now][i]) {
q[r++] = i;
acq[i] = now;
ac[i] = 1;
}
}
if (f) break;
}
//找到一个合理矩阵
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
if (g[j + n][i]) ans[i][j] = 1;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
//如果是1看看能不能变成0
if (ans[i][j] == 1) {
bfs(i, j);
}
}
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
cout << ans[i][j];
}
cout << '\n';
}
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...