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; }