• 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
    ", ans);
        }
        return 0;
    }
  • 相关阅读:
    Valid Parentheses
    3Sum
    泛型(一)
    Longest Common Prefix
    Roman to Integer
    Integer to Roman
    Container With Most Water
    知道创宇研发技能表v2.2
    anti-dns pinning 攻击
    dominator
  • 原文地址:https://www.cnblogs.com/fenice/p/5550694.html
Copyright © 2020-2023  润新知