版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_39972971/article/details/84926279
【题目链接】
【思路要点】
- 我们可以将 看做二分图的边集,找到图中每一个联通块,确定其中一个数便可以确定所有数,因此,问题等价于我们需要求解满足若干不等式 的 的一组解或指出其无解。
- 直接从高位向低位搜索即可,这部分的复杂度笔者尚不是很明确,可以肯定的是,它不会超过 ,但从实际运行的效率来看,它似乎有着更好的复杂度。
- 时间复杂度 。
【代码】
#include<bits/stdc++.h> using namespace std; const int MAXN = 1005; const int MAXM = 1e6 + 5; typedef long long ll; typedef long double ld; typedef unsigned long long ull; template <typename T> void chkmax(T &x, T y) {x = max(x, y); } template <typename T> void chkmin(T &x, T y) {x = min(x, y); } template <typename T> void read(T &x) { x = 0; int f = 1; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = x * 10 + c - '0'; x *= f; } template <typename T> void write(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) write(x / 10); putchar(x % 10 + '0'); } template <typename T> void writeln(T x) { write(x); puts(""); } int n, m, cnt, al[MAXN], ar[MAXN], bl[MAXN], br[MAXN]; int x[MAXM], l[MAXM], r[MAXM], a[MAXN], b[MAXN], c[MAXN][MAXN]; bool visa[MAXN], visb[MAXN]; int getans(int pos, int sum, int pre) { int bit = 1 << (pos + 1) >> 1, delta; if (bit == 0) delta = 0; else delta = bit * 2 - 1; for (int i = 1; i <= cnt; i++) if (max(l[i], sum ^ (pre & x[i])) > min(r[i], (sum ^ (pre & x[i])) + delta)) { return -1; } if (pos == -1) return sum; int ans = -1; ans = getans(pos - 1, sum, pre + bit); if (ans != -1) return ans; ans = getans(pos - 1, sum + bit, pre + bit); return ans; } void work(int pos, int type, int sum) { if (!type) { visa[pos] = true; x[++cnt] = sum; l[cnt] = al[pos]; r[cnt] = ar[pos]; for (int i = 1; i <= m; i++) if (!visb[i] && c[pos][i] != -1) work(i, !type, sum ^ c[pos][i]); } else { visb[pos] = true; x[++cnt] = sum; l[cnt] = bl[pos]; r[cnt] = br[pos]; for (int i = 1; i <= n; i++) if (!visa[i] && c[i][pos] != -1) work(i, !type, sum ^ c[i][pos]); } } void attach(int pos, int type, int sum) { if (!type) { a[pos] = sum; for (int i = 1; i <= m; i++) if (visb[i] && b[i] == -1 && c[pos][i] != -1) attach(i, !type, sum ^ c[pos][i]); } else { b[pos] = sum; for (int i = 1; i <= n; i++) if (visa[i] && a[i] == -1 && c[i][pos] != -1) attach(i, !type, sum ^ c[i][pos]); } } int main() { int T; read(T); while (T--) { read(n), read(m); for (int i = 1; i <= n; i++) read(al[i]), read(ar[i]), a[i] = -1; for (int i = 1; i <= m; i++) read(bl[i]), read(br[i]), b[i] = -1; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) read(c[i][j]); memset(visa, false, sizeof(visa)); memset(visb, false, sizeof(visb)); bool failed = false; for (int i = 1; i <= n && !failed; i++) if (!visa[i]) { cnt = 0, work(i, 0, 0); int tmp = getans(29, 0, 0); failed |= tmp == -1; if (tmp != -1) attach(i, 0, tmp); } for (int i = 1; i <= m && !failed; i++) if (!visb[i]) { cnt = 0, work(i, 1, 0); int tmp = getans(29, 0, 0); failed |= tmp == -1; if (tmp != -1) attach(i, 1, tmp); } for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) if (c[i][j] != -1 && (a[i] ^ b[j]) != c[i][j]) failed = true; if (failed) puts("NO"); else { puts("YES"); for (int i = 1; i <= n; i++) printf("%d ", a[i]); printf("\n"); for (int i = 1; i <= m; i++) printf("%d ", b[i]); printf("\n"); } } return 0; }