zoukankan      html  css  js  c++  java
  • 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
    ", (ans % mod + mod) % mod);
    101 }

    @Author: YouSiki

  • 相关阅读:
    从 i++ 和 ++i 说起局部变量表和操作数栈
    数据库连接情况查询相关sql语句
    db2相关语句
    BeanUtils源码详解
    Spring注解驱动开发之AOP
    Spring注解驱动开发之IOC
    正则表达式
    linux特殊符号
    linux下面如何让一个软件/命令开机自启动
    linux文件属性
  • 原文地址:https://www.cnblogs.com/yousiki/p/6410892.html
Copyright © 2011-2022 走看看