[矩阵][高斯消元][二分图]Codeforces 736D.Permutations

Description

给定一个二分图。
已知这个二分图的完备匹配的个数是奇数。
询问删除每条边后完备匹配个数是奇数还是偶数。

Solution

一个二分图的完备匹配个数就是该图邻接矩阵的积和式。
而且在膜 2 意义下积和式的值与行列式相等。
矩阵的行列式,伴随矩阵,逆之间有这样的关系

A=|A|A1
因为伴随矩阵就是
Ai,j=Mj,i
并且 |A| 为奇数,所以其实在膜 2 意义下, A=A1
答案是
|A| xor Mv,u
直接 GaussJordan 求个逆就好啦。
可以 bitset 优化哦。。

#include 
using namespace std;

const int M = 505050;
const int N = 2020;
const int INF = 1 << 30;

inline char get(void) {
    static char buf[100000], *S = buf, *T = buf;
    if (S == T) {
        T = (S = buf) + fread(buf, 1, 100000, stdin);
        if (S == T) return EOF;
    }
    return *S++;
}
template<typename T>
inline void read(T &x) {
    static char c; x = 0; int sgn = 0;
    for (c = get(); c < '0' || c > '9'; c = get()) if (c == '-') sgn = 1;
    for (; c >= '0' && c <= '9'; c = get()) x = x * 10 + c - '0';
    if (sgn) x = -x;
}

bitset A[N], iA[N];
int n, q, pos, det;
int u[M], v[M];

int main(void) {
    freopen("1.in", "r", stdin);
    read(n); read(q);
    for (int i = 0; i < q; i++) {
        read(u[i]); read(v[i]);
        A[u[i]][v[i]] = 1;
    }
    for (int i = 1; i <= n; i++)
        iA[i][i] = 1;
    for (int i = 1; i <= n; i++) {
        pos = i;
        for (int j = i + 1; j <= n; j++)
            if (A[j][i]) pos = j;
        swap(A[i], A[pos]);
        swap(iA[i], iA[pos]);
        for (int j = 1; j <= n; j++)
            if (j != i && A[j][i]) {
                A[j] ^= A[i];
                iA[j] ^= iA[i];
            }
    }
    for (int i = 0; i < q; i++)
        if (iA[v[i]][u[i]]) puts("NO");
        else puts("YES");
    return 0;
}

你可能感兴趣的:(矩阵,二分图,高斯消元)