1627. Join
Time limit: 4.0 second
Memory limit: 64 MB
Memory limit: 64 MB
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.
Samples
input | output |
---|---|
2 2 .. .. | 4 |
2 2 *. .* | 0 |
Problem Source: SPbSU ITMO contest. Petrozavodsk training camp. Winter 2008.
题意:给出一个图,'.'表示卧室,'*'表示储藏间,每个格子上下左右都有一堵墙,
然后需要打通一些卧室的墙使得卧室之间形成一棵树的方案数.
给每个卧室编个号,给可以打通的卧室加边,就是裸的生成树计数了.
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
#define maxn 111
#define mod 1000000000
#define eps 1e-10
int a[maxn][maxn], g[maxn][maxn];
char mp[maxn][maxn];
int cnt;
int n, m;
long long det () //按列化为下三角
{
long long res = 1;
for(int i = 0; i < n; ++i)
{
if (!a[i][i])
{
bool flag = false;
for (int j = i + 1; j < n; ++j)
{
if (a[j][i])
{
flag = true;
for (int k = i; k < n; ++k)
{
swap (a[i][k], a[j][k]);
}
res = -res;
break;
}
}
if (!flag)
{
return 0;
}
}
for (int j = i + 1; j < n; ++j)
{
while (a[j][i])
{
long long t = a[i][i] / a[j][i];
for (int k = i; k < n; ++k)
{
a[i][k] = (a[i][k] - t * a[j][k]) % mod;
swap (a[i][k], a[j][k]);
}
res = -res;
}
}
res *= a[i][i];
res %= mod;
}
return (res+mod)%mod;
}
#define move Move
const int move[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
bool legal (int x, int y) {
if (x < 0 || y < 0 || x >= n || y >= m)
return 0;
return 1;
}
int main()
{
//freopen("in.txt", "r", stdin);
while (cin >> n >> m) {
memset (g, -1, sizeof g);
cnt = 0;
memset (a, 0, sizeof a);
for (int i = 0; i < n; i++) {
cin >> mp[i];
for (int j = 0; j < m; j++) {
if (mp[i][j] == '.')
g[i][j] = cnt++;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) if (g[i][j] != -1) {
for (int k = 0; k < 4; k++) {
int x = i+move[k][0], y = j+move[k][1];
if (!legal (x, y) || g[x][y] == -1)
continue;
int u = g[i][j], v = g[x][y];
a[u][u]++, a[u][v] = -1;
}
}
}
n = cnt-1;
cout << det () << "\n";
}
return 0;
}