BZOJ 4031: [HEOI2015]小Z的房间 Matrix-Tree定理

题目链接:

http://www.lydsy.com/JudgeOnline/problem.php?id=4031

题解:

Matrix-tree定理解决生成树计数问题,其中用到高斯消元法求上三角矩阵,其中消元用的是辗转相除法。

代码:

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

const int mod = 1e9;
const int maxn = 111;
typedef long long LL;

int n, m, tot;
char str[maxn][maxn];
int mp[maxn][maxn];
LL C[maxn][maxn];
const int dx[] = { 0,0,-1,1 };
const int dy[] = { -1,1,0,0 };

LL Det(int n) {
    LL ret = 1;
    int f = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            C[i][j] = (C[i][j] % mod + mod) % mod;
        }
    }
    for (int i = 1; i <= n; i++) {
        for (int j = i + 1; j <= n; j++) {
            int A = C[i][i], B = C[j][i];
            while (B!=0) {
                LL t = A / B; A = A%B; swap(A, B);
                for (int k = i; k <= n; k++) {
                    C[i][k] = (C[i][k] - t*C[j][k] % mod + mod) % mod;
                }
                for (int k = i; k <= n;k++) {
                    swap(C[i][k], C[j][k]);
                }
                f = -f;
            }
        }
        ret = ret*C[i][i] % mod;
    }
    if (f == -1) ret = ((-ret)%mod + mod) % mod;
    return ret;
}

void init() {
    tot = 0;
    memset(C, 0, sizeof(C));
}

int main() {
    while (scanf("%d%d", &n, &m) == 2 && n) {
        init();
        for (int i = 0; i < n; i++) scanf("%s", str[i]);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (str[i][j] == '.') {
                    mp[i][j] = ++tot;
                }
            }
        }
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                if (str[i][j] == '.') {
                    for (int t = 0; t < 4; t++) {
                        int ii = i + dx[t], jj = j + dy[t];
                        if (ii < 0 || ii >= n || jj < 0 || jj >= m || str[ii][jj] == '*') continue;
                        C[mp[i][j]][mp[i][j]]++;
                        C[mp[i][j]][mp[ii][jj]]--;
                    }
                }
            }
        }
        LL ans=Det(tot - 1);
        printf("%lld\n", ans);
    }
    return 0;
}

 

posted @ 2016-06-01 18:53  fenicnn  阅读(233)  评论(0编辑  收藏  举报