題解 P4111 [HEOI2015]小 Z 的房間
阿新 • • 發佈:2021-06-13
題解
題目大意:給定一個無向圖,求它的生成樹個數。
一道裸的矩陣樹定理,外加一些建圖的技巧。
矩陣樹定理
對於一個 \(Laplace\) 矩陣,其去掉任意一行後的行列式即為答案。
\(Laplace\) 矩陣是一個無向圖的鄰接矩陣轉化而來的,其中 \(L_{i,i}\) 代表 \(i\) 的度數,\(L_{i,j}\) 代表 \(i->j\) 有多少條路徑(準確的說是這些路徑的權值和,求生成樹時設為 \(1\) )。
至於怎麼算,看這裡。
那麼有了這些知識,我們就可以 \(A\) 了這題。
注意,這題中模數不是質數,不能求逆元,所以我們消元時要用輾轉相除法,所以真正的時間複雜度為 \(\mathcal O((nmlog_{nm})^3)\)
Code
\(AC \kern 0.5emCODE:\)
#include<bits/stdc++.h> #define ri register signed #define p(i) ++i using namespace std; namespace IO{ char buf[1<<21],*p1=buf,*p2=buf; #define gc() p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++ inline int read() { ri x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} return x*f; } } using IO::read; namespace nanfeng{ #define int long long #define cmax(x,y) ((x)>(y)?(x):(y)) #define cmin(x,y) ((x)>(y)?(y):(x)) #define FI FILE *IN #define FO FILE *OUT static const int MOD=1e9,N=15; int id[N][N],G[N*N][N*N],deg[N*N],n,m,cnt,ans=1; char h[N][N]; inline void add(int u,int v) {G[u][v]=G[v][u]=1;} inline int main() { // FI=freopen("nanfeng.in","r",stdin); // FO=freopen("nanfeng.out","w",stdout); n=read(),m=read(); for (ri i(1);i<=n;p(i)) { scanf("%s",h[i]+1); for (ri j(1);j<=m;p(j)) if (h[i][j]=='.') id[i][j]=p(cnt); } for (ri i(1);i<=n;p(i)) { for (ri j(1);j<=m;p(j)) { if (id[i][j]&&id[i][j-1]) add(id[i][j],id[i][j-1]); if (id[i][j]&&id[i-1][j]) add(id[i][j],id[i-1][j]); } } for (ri i(1);i<=cnt;p(i)) { for (ri j(1);j<=cnt;p(j)) if (G[i][j]) p(deg[i]); } for (ri i(1);i<=cnt;p(i)) { for (ri j(1);j<=cnt;p(j)) { if (i==j) G[i][j]=deg[i]; else G[i][j]=-G[i][j]; } } cnt-=1; for (ri i(1);i<=cnt;p(i)) {//這是高斯消元,要化成三角矩陣,而不要以高斯約旦法消成對角線矩陣。 for (ri j(i+1);j<=cnt;p(j)) { while(G[j][i]) { int k=G[i][i]/G[j][i]; for (ri l(i);l<=cnt;p(l)) G[i][l]=(G[i][l]-G[j][l]*k%MOD+MOD)%MOD; swap(G[i],G[j]); ans*=-1; } } ans=(ans*G[i][i]%MOD+MOD)%MOD; } //求行列式 printf("%lld\n",(ans+MOD)%MOD); return 0; } #undef int } int main() {return nanfeng::main();}