BZOJ 4031: [HEOI2015]小Z的房间

4031: [HEOI2015]小Z的房间

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit: 878  Solved: 429
[Submit][Status][Discuss]

Description

你突然有了一个大房子,房子里面有一些房间。事实上,你的房子可以看做是一个包含n*m个格子的格状矩形,每个格子是一个房间或者是一个柱子。在一开始的时候,相邻的格子之间都有墙隔着。

你想要打通一些相邻房间的墙,使得所有房间能够互相到达。在此过程中,你不能把房子给打穿,或者打通柱子(以及柱子旁边的墙)。同时,你不希望在房子中有小偷的时候会很难抓,所以你希望任意两个房间之间都只有一条通路。现在,你希望统计一共有多少种可行的方案。

Input

第一行两个数分别表示n和m。

接下来n行,每行m个字符,每个字符都会是’.’或者’*’,其中’.’代表房间,’*’代表柱子。

Output

 一行一个整数,表示合法的方案数 Mod 10^9

Sample Input

3 3
...
...
.*.

Sample Output

15

HINT

 

对于前100%的数据,n,m<=9

 

Source

 
[Submit][Status][Discuss]

 

这就是个霍尔基夫矩阵,哦不,霍基尔夫矩阵,哦不,基尔霍夫矩阵裸题。

 

  1 #include <bits/stdc++.h>
  2 
  3 #define int long long
  4 
  5 const int mxn = 15;
  6 const int mxm = 105;
  7 const int mod = 1E9;
  8 
  9 int n, m, tot;
 10 int mrk[mxn][mxn];
 11 int map[mxn][mxn];
 12 int mat[mxm][mxm];
 13 
 14 signed main(void)
 15 {
 16     scanf("%lld%lld", &n, &m);
 17     
 18     for (int i = 1; i <= n; ++i)
 19     {
 20         static char s[mxn];
 21         scanf("%s", s + 1);
 22         
 23         for (int j = 1; j <= m; ++j)
 24             map[i][j] = (s[j] == '.');
 25     }
 26     
 27     for (int i = 1; i <= n; ++i)
 28         for (int j = 1; j <= m; ++j)
 29             if (map[i][j])
 30             {
 31                 mrk[i][j] = ++tot;
 32                 
 33                 {
 34                     int x = i - 1, y = j;
 35                     
 36                     if (map[x][y])
 37                     {
 38                         int a = mrk[i][j];
 39                         int b = mrk[x][y];
 40                         
 41                         mat[a][b] = mat[b][a] = -1;
 42                         
 43                         ++mat[a][a];
 44                         ++mat[b][b];
 45                     }
 46                 }
 47                 
 48                 {
 49                     int x = i, y = j - 1;
 50                     
 51                     if (map[x][y])
 52                     {
 53                         int a = mrk[i][j];
 54                         int b = mrk[x][y];
 55                         
 56                         mat[a][b] = mat[b][a] = -1;
 57                         
 58                         ++mat[a][a];
 59                         ++mat[b][b];
 60                     }
 61                 }
 62             }
 63     
 64     for (int i = 1; i <= tot; ++i)
 65         for (int j = 1; j <= tot; ++j)
 66             mat[i][j] = (mat[i][j] + mod) % mod;
 67             
 68     int ans = 1;
 69     
 70     for (int i = 1; i < tot; ++i)
 71     {
 72         for (int j = i + 1; j < tot; ++j)
 73             if (mat[j][i] > mat[i][i])
 74                 std::swap(mat[i], mat[j]), ans = -ans;
 75         
 76         if (mat[i][i] == 0)continue;
 77         
 78         for (int j = i + 1; j < tot; ++j)
 79         {
 80             while (mat[i][i] && mat[j][i])
 81             {
 82                 if (mat[i][i] > mat[j][i])
 83                     std::swap(mat[i], mat[j]), ans = -ans;
 84                 
 85                 int t = mat[j][i] / mat[i][i];
 86                 
 87                 for (int k = i; k < tot; ++k)
 88                     mat[j][k] = ((mat[j][k] - mat[i][k] * t % mod) % mod + mod) % mod;
 89             }
 90             
 91             if (mat[j][i])std::swap(mat[i], mat[j]), ans = -ans;
 92         }
 93     }
 94     
 95     ans = (ans + mod) % mod;
 96     
 97     for (int i = 1; i < tot; ++i)
 98         ans = ans * mat[i][i] % mod;
 99     
100     printf("%lld\n", (ans % mod + mod) % mod);
101 }

 

@Author: YouSiki

 

posted @ 2017-02-17 17:39  YouSiki  阅读(187)  评论(0编辑  收藏  举报