码迷,mamicode.com
首页 > 其他好文 > 详细

P4111 [HEOI2015]小Z的房间

时间:2018-09-17 23:00:01      阅读:173      评论:0      收藏:0      [点我收藏+]

标签:坐标   去掉   scanf   元素   namespace   target   lan   ref   ret   

P4111 [HEOI2015]小Z的房间

矩阵树定理 高斯消元

矩阵树定理:一个图的(度数矩阵-邻接矩阵)的行列式的值是图中所有生成树的方案数

求行列式:把行列式去掉任意一行一列,转成上三角矩阵,矩阵对角线上元素之积即为行列式的值

于是我们可以用高斯消元把另一半消掉,因为有模数,所以用辗转相除法。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int mod=1e9;
char q[12];
int n,m,cnt;
long long ans=1,d[102][102];
bool b[12][12],w[102];
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i){
        scanf("%s",q);
        for(int j=1;j<=m;++j) b[i][j]= q[j-1]==. ? 1:0;
    }
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j){
            int _it=(i-1)*m+j; //二维坐标映射成编号
            if(!b[i][j]) {w[_it]=1; continue;} 
            if(b[i-1][j]) --d[_it][_it-m],++d[_it][_it];
            if(b[i][j-1]) --d[_it][_it-1],++d[_it][_it];
            if(b[i+1][j]) --d[_it][_it+m],++d[_it][_it];
            if(b[i][j+1]) --d[_it][_it+1],++d[_it][_it];
        } //度数矩阵-邻接矩阵
    cnt=n*m-1; //默认去掉最后一行和最后一列
    for(int i=1;i<=cnt;++i){
        if(w[i]) continue; //是墙就跳过
        for(int j=i+1;j<=cnt;++j){
            if(w[j]) continue;
            while(d[j][i]){ //辗转相除法高斯消元
                int t=d[i][i]/d[j][i];
                for(int k=i;k<=cnt;++k) d[i][k]=(d[i][k]-t*d[j][k]+mod)%mod;
                swap(d[i],d[j]),ans=(mod-ans)%mod;
            }
        }
        ans=(ans*d[i][i]+mod)%mod; //对角线之积
    }
    printf("%lld",(ans+mod)%mod);
    return 0;
}

 

P4111 [HEOI2015]小Z的房间

标签:坐标   去掉   scanf   元素   namespace   target   lan   ref   ret   

原文地址:https://www.cnblogs.com/kafuuchino/p/9665259.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!