POJ 1830.开关问题(高斯消元)

题目链接

 

 

 


 

Solutin:

           将每个开关使用的情况当成未知数,如果开关i能影响到开关j,那么系数矩阵A[j][i]的系数为1。

           每个开关增广矩阵的值是开关k的初状态异或开关k的目标状态,这个应该很容易想到。

           方程都列好了,直接消元就好了。

 

code

/*

       解异或方程组

*/

#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;

    }

}
View Code

 

        

你可能感兴趣的:(poj)