【BZOJ4031】【Luogu P4111】[HEOI2015]小Z的房间

裸的矩阵树定理。求行列式的时候答案要在中间统计,因为交换两个行会使答案取反。

#include <bits/stdc++.h>
using namespace std;

const int N = 10 + 5;
const int M = 100 + 5;
const int mod = 1000000000;

char s[N][N];

int n, m, a[M][M], id[N][N];

void add (int u, int v) {
    --a[u][v], --a[v][u], ++a[u][u], ++a[v][v];
}

int Gauss (int n) {
    int ans = 1;
    for (int i = 1; i <= n; ++i) {
        for (int k = i + 1; k <= n; ++k) {
            while (a[k][i]) {
                int d = a[i][i] / a[k][i];
                for (int j = i; j <= n; ++j) {
					a[i][j] = (((a[i][j] - 1LL * d * a[k][j]) %mod) + mod) %mod;
				}
                swap (a[i], a[k]), ans =- ans;
            }
        }
        ans = (((1LL * ans * a[i][i]) % mod) + mod) % mod;
    }
    return ans;
}

int main () {
	cin >> n >> m;
    for (int i = 1; i <= n; ++i) cin >> s[i] + 1;
    int idx = 0;
    for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			if (s[i][j] == '.') {
				id[i][j] = ++idx;
			}
		}
	}
    for (int i = 1; i <= n; ++i) {
		for (int j = 1; j <= m; ++j) {
			if (s[i][j] == '.') {
		        if(id[i - 1][j]) add (id[i][j], id[i - 1][j]);
		        if(id[i][j - 1]) add (id[i][j], id[i][j - 1]);
    		}
		}
		 
	}
    cout << Gauss (idx - 1) << endl;
    return 0;
}
posted @ 2019-05-29 15:04  maomao9173  阅读(109)  评论(0编辑  收藏  举报