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<algorithm>
#include<cstdio>
#define rep(i,l,r) for (int i=l;i<=r;i++)
#define down(i,l,r) for (int i=l;i>=r;i--)
#define clr(x,y) memset(x,y,sizeof(x))
#define ll long long
#define maxn 109
#define mm 1000000000
using namespace std;
int n,m,p[maxn][maxn],idx;
char s[maxn][maxn];
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
ll ans,a[maxn][maxn];
int read(){
    int x=0,f=1; char ch=getchar();
    while (!isdigit(ch)){if (ch==‘-‘) f=-1; ch=getchar();}
    while (isdigit(ch)){x=x*10+ch-‘0‘; ch=getchar();}
    return x*f;
}
bool jud(int x,int y){
    if (x<1||x>n||y<1||y>m||s[x][y]!=‘.‘) return 0;
    return 1;
}
ll det(int n){
    rep(i,1,n) rep(j,1,n) a[i][j]=(a[i][j]+mm)%mm;
    ll f=1;
    rep(i,1,n) {
        rep(j,i+1,n) {
            if (a[j][i]==0) continue;
            ll A=a[i][i],B=a[j][i];
            while (B){
                ll t=A/B; A%=B; swap(A,B);
                rep(k,i,n) a[i][k]=(a[i][k]-a[j][k]*t%mm+mm)%mm;
                rep(k,i,n) swap(a[i][k],a[j][k]);
                f=-f;
            }
        }
        if (a[i][i]==0) return 0;
        ans=ans*a[i][i]%mm;
    }
    if (f==-1) ans=((mm-ans)%mm+mm)%mm;
    return ans;
}
int main(){
    n=read(); m=read();
    rep(i,1,n) scanf("%s",s[i]+1);
    rep(i,1,n) rep(j,1,m) if (s[i][j]==‘.‘) p[i][j]=++idx;
    rep(i,1,n) rep(j,1,m) if (s[i][j]==‘.‘){
        rep(k,0,3) {
            int x=i+dx[k],y=j+dy[k];
            if (jud(x,y)) {
                int u=p[i][j],v=p[x][y];
                a[u][u]++; a[u][v]--;
            }
        }
    }
    ans=1;
    printf("%lld\n",det(idx-1));
    return 0;
}
时间: 2024-08-25 18:12:20

BZOJ 4031: [HEOI2015]小Z的房间的相关文章

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

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4031 [题目大意] 你突然有了一个大房子,房子里面有一些房间. 事实上,你的房子可以看做是一个包含n*m个格子的格状矩形, 每个格子是一个房间或者是一个柱子.在一开始的时候,相邻的格子之间都有墙隔着. 你想要打通一些相邻房间的墙,使得所有房间能够互相到达. 在此过程中,你不能把房子给打穿,或者打通柱子(以及柱子旁边的墙). 同时,你不希望在房子中有小偷的时候会很难抓, 所以你希望任意

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的房间 &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个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时候,相邻的格子之间都有墙隔着. 你想要打通一些相邻房间的墙,使得所有房间能够互相到达.在此过程中,你不能把房子给打穿,或者打通柱子(以及柱子旁边的墙).同时,你不希望在房子中有小偷的时候会很难抓,所

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[

P4111 [HEOI2015]小Z的房间

你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子.在一开始的时候,相邻的格子之间都有墙隔着.你想要打通一些相邻房间的墙,使得所有房间能够互相到达.在此过程中,你不能把房子给打穿,或者打通柱子(以及柱子旁边的墙).同时,你不希望在房子中有小偷的时候会很难抓,所以你希望任意两个房间之间都只有一条通路.现在,你希望统计一共有多少种可行的方案. 矩阵树求生成树个数模板题 度数矩阵-邻接矩阵=拉普拉斯矩阵 求拉普拉斯矩阵的任意一个代数余子数即可 #define int l