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

【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=4031

【题目大意】

  你突然有了一个大房子,房子里面有一些房间。
  事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,
  每个格子是一个房间或者是一个柱子。在一开始的时候,相邻的格子之间都有墙隔着。
  你想要打通一些相邻房间的墙,使得所有房间能够互相到达。
  在此过程中,你不能把房子给打穿,或者打通柱子(以及柱子旁边的墙)。
  同时,你不希望在房子中有小偷的时候会很难抓,
  所以你希望任意两个房间之间都只有一条通路。现在,你希望统计一共有多少种可行的方案。

【题解】

  根据任意两个房间之间只有一条通路我们可以知道这题要求的是生成树的方案数,
  那么我们先求出这个图的基尔霍夫矩阵,然后求余子式就是答案,处理一下取模即可。

【代码】

#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
#define rep(i,n,m) for(int i=n;i<=m;i++)
const LL mod=1000000000;
int dx[]={0,0,1,-1},dy[]={1,-1,0,0};
int n,m,id;
char mp[110][110];
LL a[110][110],p[110][110];
int det(int n){
    LL ans=1,f=1;
    rep(i,1,n)rep(j,1,n)a[i][j]=(a[i][j]+mod)%mod;
    rep(i,1,n){
        rep(j,i+1,n){
            LL A=a[i][i],B=a[j][i];
            while(B!=0){
                LL t=A/B; A%=B; swap(A,B);
                for(int k=1;k<=n;k++)a[i][k]=(a[i][k]-t*a[j][k]%mod+mod)%mod;
                for(int k=1;k<=n;k++)swap(a[i][k],a[j][k]);
                f=-f;
            }
        }if(!a[i][i])return 0;
        ans=ans*a[i][i]%mod;
    }if(f==-1)return (mod-ans)%mod;
    return ans;
}
bool check(int x,int y){if(x<1||y<1||x>n||y>m||mp[x][y]!=‘.‘)return 0;return 1;}
int main(){
    scanf("%d%d",&n,&m);
    rep(i,1,n)scanf("%s",mp[i]+1);
    rep(i,1,n)rep(j,1,m)if(mp[i][j]==‘.‘)p[i][j]=++id;
    rep(i,1,n)rep(j,1,m)if(mp[i][j]==‘.‘){
        rep(k,0,4){
            int x=i+dx[k],y=j+dy[k];
            if(check(x,y)){int u=p[i][j],v=p[x][y];a[u][u]++;a[u][v]--;}
        }
    }printf("%d\n",det(id-1));
    return 0;
}
时间: 2024-12-10 23:10:03

BZOJ 4031 [HEOI2015]小Z的房间(Matrix-Tree定理)的相关文章

BZOJ 4031: [HEOI2015]小Z的房间

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=4031 矩阵树定理. 基尔霍夫矩阵就是对于i=j,a[i][j]=d[i],对于i!=j,a[i][j]=a[j][i]=-1(如果可以连边的话),否则就是0. 然后把这个矩阵去掉第i行第i列,解这个行列式(删掉第n行比较方便嘛..) 模数比较坑爹,并不是一个质数,所以辗转相除. #include<string> #include<iostream> #include<al

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

题目大意:给定一张地图,求生成树个数 Matrix-Tree定理直接上 不过模数是109,不能直接求逆元 因此消元的时候辗转相除一下就好了 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define M 110 #define MOD 1000000000 using namespace std; const int dx[]={0,0,1,-1}

【BZOJ 4031】 4031: [HEOI2015]小Z的房间 (Matrix-Tree Theorem)

4031: [HEOI2015]小Z的房间 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1089  Solved: 533 Description 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时候,相邻的格子之间都有墙隔着. 你想要打通一些相邻房间的墙,使得所有房间能够互相到达.在此过程中,你不能把房子给打穿,或者打通柱子(以及柱子旁边的墙).同

【BZOJ4031】[HEOI2015]小Z的房间 矩阵树定理

[BZOJ4031][HEOI2015]小Z的房间 Description 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时候,相邻的格子之间都有墙隔着. 你想要打通一些相邻房间的墙,使得所有房间能够互相到达.在此过程中,你不能把房子给打穿,或者打通柱子(以及柱子旁边的墙).同时,你不希望在房子中有小偷的时候会很难抓,所以你希望任意两个房间之间都只有一条通路.现在,你希望统计一共有多少种可行的方案.

bzoj4031 [HEOI2015]小Z的房间——矩阵树定理

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4031 矩阵树定理的模板题(第一次的矩阵树定理~): 有点细节,放在注释里了. 代码如下: #include<iostream> #include<cstdio> #include<cstring> using namespace std; typedef long long ll; int const mod=1e9; int n,m,a[105][105],d[

[HEOI2015] 小Z的房间 - 矩阵树定理

#include <bits/stdc++.h> using namespace std; #define int long long const int N = 105; const int mod = 1e+9; namespace mat { int a[N][N]; int n,p=1; int Gauss() { int ans = 1; for(int i = 1; i < n; i ++) { for(int j = i + 1; j < n; j ++) while

【bzoj4031】[HEOI2015]小Z的房间 &amp;&amp; 【bzoj4894】天赋 (矩阵树定理)

来两道矩阵树模板: T1:[bzoj4031][HEOI2015]小Z的房间 Description 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时候,相邻的格子之间都有墙隔着.你想要打通一些相邻房间的墙,使得所有房间能够互相到达.在此过程中,你不能把房子给打穿,或者打通柱子(以及柱子旁边的墙).同时,你不希望在房子中有小偷的时候会很难抓,所以你希望任意两个房间之间都只有一条通路.现在,你希望统计

P4111 [HEOI2015]小Z的房间 生成树计数

这个题是生成树计数的裸题,中间构造基尔霍夫矩阵,然后构成行列式,再用高斯消元就行了.这里高斯消元有一些区别,交换两行行列式的值变号,且消元只能将一行的数 * k 之后加到别的行上. 剩下就没啥了... 找到一个写的特别详细的. il int det() { int ans = 1; for (ri i = 1; i <= sz; ++i) { // 当前在消第i个(i,i) for (ri j = i + 1, t; j <= sz; ++j) { // 把它下面对应的位置消成0 while

Bzoj4031 [HEOI2015]小Z的房间

Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1041  Solved: 504 Description 你突然有了一个大房子,房子里面有一些房间.事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时候,相邻的格子之间都有墙隔着. 你想要打通一些相邻房间的墙,使得所有房间能够互相到达.在此过程中,你不能把房子给打穿,或者打通柱子(以及柱子旁边的墙).同时,你不希望在房子中有小偷的时候会很难抓,所