1627 Join 生成樹計數模板題
URAL - 1627 Join
Businessman Petya recently bought a new house. This house has one floor with n × m square rooms, placed in rectangular lattice. Some rooms are pantries and the other ones are bedrooms. Now he wants to join all bedrooms with doors in such a way that there will be exactly one way between any pair of them. He can make doors only between neighbouring bedrooms (i.e. bedrooms having a common wall). Now he wants to count the number of different ways he can do it.
Input
First line contains two integers n and m (1 ≤ n, m ≤ 9) — the number of lines and columns in the lattice. Next n lines contain exactly m characters representing house map, where "." means bedroom and "*" means pantry. It is guaranteed that there is at least one bedroom in the house.
Output
Output the number of ways to join bedrooms modulo 10 9.
Example
input | output |
---|---|
2 2 .. .. |
4 |
2 2 *. .* |
0 |
#include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #include <map> using namespace std; const int maxn = 100 + 10; const int maxm = 1010025; const int INF = 0x3f3f3f3f; const int mod = 1e9; const double eps = 1e-8; #define type long long int n,m; int d[maxn]; int g[maxn][maxn]; type c[maxn][maxn]; type det(type a[][maxn],int n) { type ret=1; for(int i=1;i<=n;i++) { for(int j=i+1;j<=n;j++) { while(a[j][i]) { type t=a[i][i]/a[j][i]; for(int k=i;k<=n;k++) a[i][k]=(((a[i][k]-a[j][k]*t)%mod)+mod)%mod; for(int k=i;k<=n;k++) swap(a[i][k],a[j][k]); ret=-ret; } } if(a[i][i]==0) return 0; ret=(((ret*a[i][i])%mod)+mod)%mod; } if(ret<0) ret=-ret; return ret%mod; } type num_st(int n) { for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) { if(i == j) c[i][j] = d[i]; else c[i][j] = -g[i][j]; } /* for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) printf("%lld%c",c[i][j],j == n ? '\n' : ' '); */ return det(c,n-1); } typedef pair<int,int> P; map <P,int> mp; int tot = 0; string s[10]; int fx[4] = {0,0,1,-1}; int fy[4] = {1,-1,0,0}; bool check(int x, int y) { if(x < 0 || y < 0 || x >= n || y >= m) return false; if(s[x][y] == '.') return true; } int main() { scanf("%d%d",&n,&m); for(int i = 0; i < n; i++) { cin >> s[i]; for(int j = 0; j < m; j++) if(s[i][j] == '.') mp[P(i,j)] = ++tot; } memset(g,0,sizeof(g)); for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) { if(s[i][j] == '.') for(int k = 0; k < 4; k++) { int di = i + fx[k]; int dj = j + fy[k]; if(check(di,dj)) { int u = mp[P(i,j)]; int v = mp[P(di,dj)]; g[u][v] = g[v][u] = 1; } } } for(int i = 1; i <= tot; i++) for(int j = 1; j <= tot; j++) if(i != j) d[i] += g[i][j]; type ans = num_st(tot); printf("%lld\n",ans); return 0; }