POJ 1830.开关问题(高斯消元)
Solutin:
将每个开关使用的情况当成未知数,如果开关i能影响到开关j,那么系数矩阵A[j][i]的系数为1。
每个开关增广矩阵的值是开关k的初状态异或开关k的目标状态,这个应该很容易想到。
方程都列好了,直接消元就好了。
code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/* 解异或方程组 */ #include <iostream> #include <cstring> using namespace std; const int MAXN = 50; int prim[MAXN]; int A[MAXN][MAXN]; int Gauss (int n, int m) { int col = 0, row = 0, tem, k = 0; for (; col < m && row < n; ++col) { for (tem = row; tem < n && A[tem][col] == 0; ++tem); if (tem == n) continue; if (tem != row) { for (int i = 0; i <= n; ++i) swap (A[row][i], A[tem][i]); } for (int i = row + 1; i <= n; ++i) { if (A[i][col]) for (int j = col; j <= m; ++j) A[i][j] ^= A[row][j]; } row++; } for (int i = row; i < n; ++i) if (A[i][n] != 0) return -1; return m - row; } int n, m, cs, S, T; int main() { ios::sync_with_stdio (0); cin >> cs; while (cs--) { cin >> n; S = T = 0; for (int i = 0, x; i < n; ++i) { cin >> x; if (x) S |= (1 << i); } for (int i = 0, x; i < n; ++i) { cin >> x; if (x) T |= (1 << i); } T ^= S; memset (A, 0, sizeof A); for (int i = 0; i < n; ++i){ if (T & (1 << i) ) A[i][n] = 1; A[i][i]=1; } int x, y; while (cin >> x >> y, x && y) A[y - 1][x - 1] = 1; int p = Gauss (n, n); if (p < 0) cout << "Oh,it's impossible~!!" << endl; else cout << (1 << p) << endl; } }