Switching problem (Gaussian elimination method)

Total time limit: 1000ms
Memory limit: 65536kB

Description
of N identical switches, each switch have a certain contact, whenever you open or close a switch when the other switch associated with this switch will change accordingly, these phases i.e. If the state of the associated switch was originally on, it would change to off, and if it was off, it would change to on. Your goal is to make the last N switches reach a specific state after several switch operations. For any switch, only one switch operation can be performed at most. Your task is to calculate how many ways to reach a specified state. (Does not count the sequence of switch operations)

Input
There is a number K in the first line of input, indicating that there are K groups of test data below.
The format of each group of test data is as follows: the
first line has a number N (0 <N <29) and the
second line has N 0 or 1 numbers, indicating the N switch states at the beginning.
The number of N 0 or 1 in the third row indicates the state of the N switches after the operation is completed.
The next two numbers IJ in each line indicate that if the I switch is operated, the state of the J switch will also change. Each group of data ends with 0 0.

Output
If there is a feasible method, output the total number, otherwise output "Oh,it's impossible~!!" Without quotes

Sample input
2
3
0 0 0
1 1 1
1 2
1 3
2 1
2 3
3 1
3 2
0 0
3
0 0 0
1 0 1
1 2
2 1
0 0

The sample output is
4
Oh, it's impossible~!!

Tips
Description of the first group of data:
There are four methods in total:
Operation switch 1
Operation switch 2
Operation switch 3
Operation switch 1, 2, 3 (do not record the order)

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 35;
bool a[MAXN][MAXN];

inline int read() {
    
    
    int x; scanf("%d", &x); return x;
}

int gauss(int n)
{
    
    
    int rank = 0;
    for (int d = 0; d < n; ++d) {
    
     /* d for diagonal */
        int i;
        /* try to find first line whose d'th element = 1 */
        for (i = d; i < n; ++i)
            if (a[i][d] == 1)
                break;

        /* not found */
        if (i == n)
            continue;
        
        /* found */

        /* Step 1: make the d'th element of rank'th line to be 1, by swapping i'th line and rank'th line, including the rightmost column */
        for (int j = 0; j <= n; ++j) 
            swap(a[rank][j], a[i][j]);
        /* Step 2: eliminating the following line if the d'th element = 1, including the rightmost column */
        for (i = rank+1; i < n; ++i) 
            if (a[i][d])
                for (int j = 0; j <= n; ++j) 
                    a[i][j] ^= a[rank][j];

        ++rank;
    }

    /* up to now, the rank+'th line should be all 0 */
    /* if the rightmost column is 1, bad equation, return -1 */
    for (int i = rank; i < n; ++i)
        if (a[i][n])
            return -1;

    /* otherwise, return the rank */
    return rank;
}

int main()
{
    
    
    int K = read();
    for (int k = 0; k < K; ++k) {
    
    
        memset(a, 0, sizeof(a));
        int N = read();
        for (int i = 0; i < N; ++i) 
            a[i][N] ^= read();
        for (int i = 0; i < N; ++i) 
            a[i][N] ^= read();
        for (int x = 0; x < N; ++x)
            a[x][x] = 1;
        for (;;) {
    
    
            int x = read()-1, y = read()-1;
            if (x == -1)
                break;
            a[y][x] = 1;
        }
        int rank = gauss(N);
        if (rank == -1)
            printf("Oh,it's impossible~!!\n");
        else 
            printf("%d\n", 1<<(N-rank));
    }
    system("pause");
    return 0;
}
analysis
  1. Regarding the Gaussian elimination method, the code comments have been very detailed. The gauss function is actually a general solving function. If there is no solution, it returns -1, and if there is a solution, it returns the rank of the matrix.
  2. Array a, rows represent switches, and columns represent solutions (each switch "leads" a solution, so the number of rows and columns is equal)
  3. Why it can be eliminated can be understood as defining an equivalence problem, and the solution of the equivalence problem corresponds to the solution of the original problem one to one. Gaussian elimination does this, and the exclusive OR operation is reversible, so it's no problem.
  4. Not only row elimination is equivalent, but column elimination is also equivalent. In the code, we calculated the rank by row elimination, and then we can make up for it and perform column elimination, and finally only 1 on the diagonal is left.
  5. Rows with 1 must be taken, rows without 1s can be taken or not, so the final number of plans is 2 n − rank 2^{n-rank}2nrank

This question allows us to review the exquisite Gaussian elimination method from the algebraic perspective.

Guess you like

Origin blog.csdn.net/w112348/article/details/110941960